package edu.fiu.jtlex.data;

import java.util.HashSet;
import java.util.Set;

/**
 * Default implementation of {@code ITimex}.
 * 
 * @author ceber003
 */
public class Timex implements ITimex {

	// immutable instance fields
	private final int tID;
	private final TimexType type;
	private final String value;
	private final TimexMod mod; // optional attribute
	private final boolean temporalFunction;
	private final int anchorID; // optional attribute
	private final FunctionInDocument documentFunction;
	private final int beginPoint;
	private final int endPoint;
	private final String quant;
	private final String freq;
	private final String phrase;
	private Set<ILink> inLinks;
	private Set<ILink> outLinks;

	/**
	 * Creates a new Timex with the specified information.
	 * 
	 * @param tID              id of the timex; may not be negative
	 * @param type             the type of the timex may not be null
	 * @param value            the value attribute of the timex
	 * @param mod              the mod of the value, is optional
	 * @param temporalFunction true or false
	 * @param anchorID         the id of another timex anchored to the current
	 *                         timex, optional
	 * @param documentFunction the function a timex is providing within the
	 *                         document, is 'NONE' when not specified.
	 * @param beginpoint       beginpoint is used if the timex is anchored to
	 *                         another, can be null
	 * @param endpoint         end is used if timex is anchored to another timex,
	 *                         can be null
	 * @param quant            used only if timex type is 'SET' is the literal
	 *                         describing the timex rate of occurrence
	 * @param freq             used only if timex type is 'SET' is the frequency the
	 *                         timex occurs
	 * @throws NullPointerException     if type or value is null
	 * @throws IllegalArgumentException if tID, acnhorId, beginPoint, or endPoint is
	 *                                  negative
	 * 
	 */
	public Timex(int tID, TimexType type, String value, TimexMod mod, boolean temporalFunction, int anchorID,
			FunctionInDocument documentFunction, int beginPoint, int endPoint, String quant, String freq,
			String phrase) {

		if (tID < 0) {
			throw new IllegalArgumentException("Error: Time id can't be less than zero.");
		}
		if (type == null) {
			throw new NullPointerException("Error: Timex type can't be Null.");
		}
		if (value == null) {
			throw new NullPointerException("Error: Timex value can't be Null.");
		}
		if (anchorID < 0) {
			throw new IllegalArgumentException("Error: Anchor id can't be less than zero.");
		}
		if (beginPoint < 0) {
			throw new IllegalArgumentException("Error: beginPoint id can't be less than zero.");
		}
		if (endPoint < 0) {
			throw new IllegalArgumentException("Error: endPoint id can't be less than zero.");
		}

		this.tID = tID;
		this.type = type;
		this.value = value;
		this.mod = mod;
		this.temporalFunction = temporalFunction;
		this.anchorID = anchorID;
		this.documentFunction = documentFunction;
		this.beginPoint = beginPoint;
		this.endPoint = endPoint;
		this.quant = quant;
		this.freq = freq;
		this.phrase = phrase;
		this.inLinks = new HashSet<>();
		this.outLinks = new HashSet<>();

		if (documentFunction == null) {
			documentFunction = FunctionInDocument.NONE;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getTimexId()
	 */
	public int getId() {
		return tID;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getTimexIdStr()
	 */
	public String getIdStr() {
		String tId = "t" + tID;
		return tId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getTimexType()
	 */
	public TimexType getType() {
		return type;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getValue()
	 */
	public String getValue() {
		return value;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getMod()
	 */
	public TimexMod getMod() {
		return mod;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getTemporalFunction()
	 */
	public boolean getTemporalFunction() {
		return temporalFunction;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getAnchorTimexId()
	 */
	public int getAnchorTimeId() {
		return anchorID;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getAnchorTimexIdStr()
	 */
	public String getAnchorTimeIdStr() {
		String anchorId = "t" + anchorID;
		return anchorId;
	}

	// public String getValueFromFunction();

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getFunction()
	 */
	public FunctionInDocument getFunction() {
		return documentFunction;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getBeginPoint()
	 */
	public int getBeginPoint() {
		return beginPoint;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getBeginPointStr()
	 */
	public String getBeginPointStr() {
		String beginPointId = "t" + beginPoint;
		return beginPointId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getEndPoint()
	 */
	public int getEndPoint() {
		return endPoint;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getEndPointStr()
	 */
	public String getEndPointStr() {
		String endPointId = "t" + endPoint;
		return endPointId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getQuant()
	 */
	public String getQuant() {
		return quant;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getFreq()
	 */
	public String getFreq() {
		return freq;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.fiu.jtlex.data.ITimex#getPhrase()
	 */
	public String getPhrase() {
		return phrase;

	}

	/**
	 * Add a link to the set of OUT links from this node.
	 * @param link: A new OUT link from this node.
	 */
	public void addOutLink(ILink link) {
		outLinks.add(link);
	}
	/**
	 * Add a link to the set of IN links from this node.
	 * @param link: A new IN link incoming to this node.
	 */
	public void addInLink(ILink link) {
		inLinks.add(link);
	}

	/**
	 * Returns the set of TimeML links which come from this node.
	 * @return Set<ILink> 
	 */
	public Set<ILink> getOutLinks() {
		return outLinks;
	}
	/**
	 * Returns the set of TimeML links which come to this node.
	 * @return Set<ILink> 
	 */
	public Set<ILink> getInLinks() {
		return inLinks;
	}
	/**
	 * Removes a TimeML link from the set of links that start in this node.
	 * @param link: A new OUT link to remove from the set of outgoing links.
	 */
	public void removeOutLink(ILink link) {
		outLinks.remove(link);
	}
	/**
	 * Add a link to the set of OUT links from this node.
	 * @param link: A new IN link to remove from the set of incoming links.
	 */
	public void removeInLink(ILink link) {
		inLinks.remove(link);
	}
}
