package mTripleApl.micro;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import mTripleApl.*;
import java.util.*;

/**
 * Example: BlockWorld ACTUATOR, Deliberative cycle.
 *
 * Create a agent with:
 * - one Actuator to print in a BlockWorld (Canvas) object
 *
 * @author Fernando Koch
 */

public class TestMicro003
    extends MIDlet
    implements CommandListener {

  BlockWorld blockWorld;

  /**
   * MIDLET INTERFACE.
   * Start MIDlet run.
   */
  public void startApp() {

    // create BlockWorld
    this.blockWorld = new BlockWorld(20, 10, 10);
    this.blockWorld.setCommandListener(this);
    this.blockWorld.addCommand(new Command("Exit", Command.EXIT, 1));
    Display.getDisplay(this).setCurrent(this.blockWorld);
    this.blockWorld.repaint();

    // create agent
    DeliberativeAgent ag = new DeliberativeAgent("micro");
    ag.setTrace(6);

    // load knowledge bases
    ag.addCapability(
        "{pos(X,Y)} West() { NOT pos(X,Y) , pos(X-1,Y) , BlockMove(west)}");
    ag.addCapability(
        "{pos(X,Y)} East() { NOT pos(X,Y) , pos(X+1,Y) , BlockMove(east)}");
    ag.addCapability(
        "{pos(X,Y)} North() { NOT pos(X,Y) , pos(X,Y+1) , BlockMove(north)}");
    ag.addCapability(
        "{pos(X,Y)} South() { NOT pos(X,Y) , pos(X,Y-1) , BlockMove(south)}");
    ag.addPlanRule("goBase <- pos(X,Y) AND base(X,Y) | SKIP.");
    ag.addPlanRule(
        "goBase <- pos(X,Y) AND base(A,B) AND X>A | West() , goBase().");
    ag.addPlanRule(
        "goBase <- pos(X,Y) AND base(A,B) AND X<A | East() , goBase().");
    ag.addPlanRule(
        "goBase <- pos(X,Y) AND base(A,B) AND Y>B | South() , goBase().");
    ag.addPlanRule(
        "goBase <- pos(X,Y) AND base(A,B) AND Y<B | North() , goBase().");
    ag.addBelief("pos(10,10)");
    ag.addBelief("base(19,19)");
    ag.addBelief("base(0,0)");
    ag.addGoal("goBase()");

    // set costs/values
    ag.setCost("South()", 5);
    ag.setCost("North()", 4);
    ag.setCost("East()", 5);
    ag.setCost("West()", 10);
    ag.setWorth("goBase()", 10);

    // attach actuator
    ag.addActuator("BlockMove(X)", new BlockWorldActuator2(this.blockWorld));

    // deliberate
    ag.deliberate();

    // print agent mental state
    System.out.println(ag.toString());

    // print agent mental state
    System.out.println(ag.getStatistics());
  }

  /**
   * MIDLET INTERFACE.
   * Handle pausing the MIDlet
   */
  public void pauseApp() {
  }

  /**
   * MIDLET INTERFACE.
   * Handle destroying the MIDlet
   *
   * @param unconditional for no cry
   */
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }

  /**
   * Handle command events
   *
   * @param command incoming
   * @param displayable element
   */
  public void commandAction(Command command, Displayable displayable) {
    if (command.getCommandType() == Command.EXIT) {
      destroyApp(true);
    }
  }
}

/**
 * ACTUATOR TO BLOCK WORLD
 */
class BlockWorldActuator2
    implements ActuatorInterface {
  BlockWorld blockWorld;

  // create: associate to world
  public BlockWorldActuator2(BlockWorld blockWorld) {
    this.blockWorld = blockWorld;
  }

  // called during registration
  public void register(String agentName){}

  // called during reset
  public void reset(){}

  // called from Deliberation engine
  public boolean actuator(Hashtable parameters) {
    String command = (String) parameters.get("X");
    if (command != null) {
      System.out.println("Order to go " + command);

      if (command.startsWith("west")) {
        this.blockWorld.moveX( -1);
      }
      else if (command.startsWith("east")) {
        this.blockWorld.moveX(1);
      }
      else if (command.startsWith("north")) {
        this.blockWorld.moveY(1);
      }
      else if (command.startsWith("south")) {
        this.blockWorld.moveY( -1);
      }
    }
    return true;
  }
}

