package edu.calpoly.csc480.Wumpus.Agent;

import com.bcurry.www.awt.*;

import edu.calpoly.csc480.Wumpus.Area.*;
import edu.calpoly.csc480.Wumpus.Tile.*;

public abstract class Action
{
	public static abstract class DirectionAction extends Action {
		public DirectionAction() {
			head = new Direction();
		}

		public String toString() {
			return getName() + " " + Direction.names[head.getDrift()];
		}

		public final Direction getDirection()		{return head;}

		protected Direction head;
	}

	public static class Climb extends Action {
		public String getName()						{return "Climbing";}
		public void commit(Actuator actuator)	{actuator.climb(this);}

		public void tell(KnowledgeBase kb) {
			if (kb.getHusk().getFact(Fact.exit).isTrue()) {
				kb.getHusk().set(Husk.agent, false);
			}
		}
	}

	public static class Grab extends Action {
		public String getName()						{return "Grabbing";}
		public void commit(Actuator actuator)	{actuator.grab(this);}
		
		public void tell(KnowledgeBase kb) {
			if (kb.getHusk().getFact(Fact.gold).isTrue()) {
				kb.getHusk().getFact(Fact.gold).set(false);
				kb.setCurrentAVS(kb.getFleeingAVS());
			}
		}
	}

	public static class Shoot extends DirectionAction {
		public String getName()						{return "Shooting";}
		public void setDirection(int drift)		{head.setDrift(drift);}
		public void commit(Actuator actuator)	{actuator.shoot(this);}
		
		public void tell(KnowledgeBase kb) {
			kb.setAmmo(false);
		}
	}

	public static class Move extends DirectionAction {
		public Move() {
			head = new Direction();
		}

		public String getName()						{return "Moving";}
		public final Husk getSource()				{return src;}
		public final Husk getTarget()				{return trg;}

		public void setCourse(Husk trg, Husk src) {
			this.trg = trg;
			this.src = src;

			if (trg != null && src != null) {
				head.setPoint(BasicPoint.sub(trg, src));
			}
		}

		public boolean equals(Object base) {
			Move that;

			if (base instanceof Move) {
				that = (Move)base;
				
				return (
				 src.equals(that.getSource()) &&
				 trg.equals(that.getTarget())
				);
			}
			else {
				return false;
			}
		}

		public void commit(Actuator actuator)	{actuator.move(this);}

		public void tell(KnowledgeBase kb) {
			Move copy;

			kb.setHusk(trg);

			copy = new Move();
			copy.setCourse(trg, src);
			kb.getPath().push(copy);
		}

		protected Husk src, trg;
	}

	public static class Flee extends Action.Move {
		public String getName()						{return "Fleeing";}

		public void tell(KnowledgeBase kb) {
			kb.setHusk(trg);
		}
	}

	public Action() {
	}

	public String toString()	{return getName();}

	public abstract String getName();

	public abstract void commit(Actuator actuator);
	public abstract void tell(KnowledgeBase kb);

	protected KnowledgeBase kb;
}