package edu.calpoly.csc480.Wumpus.Agent;

import edu.calpoly.csc480.Wumpus.Agent.Rule.*;

public abstract class Fact
{
	public static final int
	 ok = 0, wall = 1, exit = 2, pit = 3, wumpus = 4, gold = 5,
	 numFacts = 6;

	public static final byte TRUE = 0, FALSE = 1, FUZZY = 2;

	public static abstract class Positional extends Fact {
		public abstract int getHuskType();

		public void set(boolean truth) {
			husk.set(getHuskType(), truth);
			super.set(truth);
		}
	}

	public static abstract class Conformable extends Fact.Positional {
		public abstract int getRuleType();

		public void setKnowledgeBase(KnowledgeBase kb) {
			super.setKnowledgeBase(kb);
			this.rule = (Rule.Informable)kb.getRule(getRuleType());
		}

		public void set(boolean truth) {
			super.set(truth);
			rule.inform(husk);
		}

		protected Rule.Informable rule;
	}

	public static class OK extends Fact {
		public int getFactType()		{return Fact.ok;}
	}

	public static class Wall extends Fact.Conformable {
		public int getFactType()		{return Fact.wall;}
		public int getHuskType()		{return Husk.wall;}
		public int getRuleType()		{return Percept.bump;}
	}

	public static class Exit extends Fact.Positional {
		public int getFactType()		{return Fact.exit;}
		public int getHuskType()		{return Husk.exit;}
	}

	public static class Pit extends Fact.Conformable {
		public int getFactType()		{return Fact.pit;}
		public int getHuskType()		{return Husk.pit;}
		public int getRuleType()		{return Percept.breeze;}
	}

	public static class Wumpus extends Fact.Conformable {
		public int getFactType()		{return Fact.wumpus;}
		public int getHuskType()		{return Husk.wumpus;}
		public int getRuleType()		{return Percept.stench;}
	}

	public static class Gold extends Fact.Conformable {
		public int getFactType()		{return Fact.gold;}
		public int getHuskType()		{return Husk.gold;}
		public int getRuleType()		{return Percept.glitter;}
	}

	public Fact() {
		bool = FUZZY;
	}

	public boolean isTrue()				{return bool == TRUE;}
	public boolean isFalse()			{return bool == FALSE;}
	public boolean isFuzzy()			{return bool == FUZZY;}

	public abstract int getFactType();

	public void setHusk(Husk husk) {
		this.husk = husk;
	}

	public void setKnowledgeBase(KnowledgeBase kb) {
		this.kb = kb;
	}

	public void set(boolean truth) {
		bool = (truth ? TRUE : FALSE);
	}

	protected byte bool;
	protected Husk husk;	
	protected KnowledgeBase kb;
}