package com.tandbergtv.metadatamanager.search;

import java.util.List;

import org.w3c.util.InvalidDateException;

import com.tandbergtv.watchpoint.search.Entity;
import com.tandbergtv.workflow.driver.search.ListParameter;
import com.tandbergtv.workflow.driver.search.SearchOperator;
import com.tandbergtv.workflow.driver.search.SearchType;
import com.tandbergtv.workflow.driver.search.ValueParameter;

/**
 * @author vgoyal
 * 
 */
public class ListFieldInfo extends FieldInfo {

	SearchOperator operator; /* can only be IN */
	List<String> values;

	/**
	 * 
	 */
	public ListFieldInfo() {
		super();
		this.operator = SearchOperator.IN;
		this.isConjunction = true;
	}

	/**
	 * 
	 * @param ttvxpath
	 * @param values
	 */
	public ListFieldInfo(String ttvxpath, List<String> values) {
		super();
		this.ttvxpath = ttvxpath;
		this.operator = SearchOperator.IN;
		this.values = values;
		this.isConjunction = true;
	}

	/**
	 * 
	 * @param ttvxpath
	 * @param values
	 */
	public ListFieldInfo(String ttvxpath, List<String> values, SearchOperator operator) {
		super();
		this.ttvxpath = ttvxpath;
		this.operator = operator;
		this.values = values;
		this.isConjunction = true;
	}
	
	/**
	 * 
	 * @param ttvxpath
	 * @param values
	 * @param isConjunction
	 */
	public ListFieldInfo(String ttvxpath, List<String> values, SearchOperator operator, boolean isConjunction) {
		super();
		this.ttvxpath = ttvxpath;
		this.operator = operator;
		this.values = values;
		this.isConjunction = isConjunction;
	}

	/**
	 * @return the operator
	 */
	public SearchOperator getOperator() {
		return operator;
	}

	/**
	 * @return the values
	 */
	public List<String> getValues() {
		return values;
	}

	/**
	 * @param values
	 *            the values to set
	 */
	public void setValues(List<String> values) {
		this.values = values;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void createEntity(String property, Entity assetEntity) {
		String valueColumnName = "";
		SearchType searchType = SearchType.STRING;
		
		Entity field = new Entity("field", property, "f");

		if(ttvxpath.contains("CustomField[@name")) {
			handleCustomFieldValueParameter(field);
			
			field.addParameter(new ValueParameter("ttvXPath",
					SearchType.STRING, ttvxpath, SearchOperator.EQUAL));			
		} else {
			field.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, ttvxpath, SearchOperator.EQUAL));

			//find out the datatype for the xpath
			valueColumnName = getValueColumnName();
			searchType = getSearchTypeBasedOnColumn(valueColumnName);
			
			ListParameter listParam = new ListParameter(valueColumnName, searchType, getOperator());
			
			for (String value : values) {
				listParam.addValue(value);
			}
			
			field.addParameter(listParam);
		}

		ValueParameter assetTypeParam = addAssetTypeCriteria();
		if(assetTypeParam != null) {
			field.addParameter(assetTypeParam);
		}

		assetEntity.addParameter(field, isConjunction());
	}
	
	
	
	/**
	 * This method is a piece of beauty. it jumps through so many hoops
	 * (if/else, try/catch) to try to find the datatype for the custom field
	 *
	 * REMOVE this method once we have the functionality to find the datatype
	 * for a customfield
	 * 
	 * @param field
	 */
	private void handleCustomFieldValueParameter(Entity field) {
		boolean isInt = true;
		boolean isFloat = true;
		boolean isDate = false;
		boolean isString = false;
		
		String val = "";
		if(values != null) {
			val = values.get(0); 
		}
		
		try {
			Integer.parseInt(val);
			ListParameter listParam = new ListParameter("intValue", SearchType.NUMERIC, getOperator());
			for (String value : values) {
				listParam.addValue(value);
			}
			field.addParameter(listParam);
		} catch (NumberFormatException e) {
			isInt = false;
		}

		if (!isInt) {
			try {
				Float.parseFloat(val);
				ListParameter listParam = new ListParameter("floatValue", SearchType.NUMERIC, getOperator());
				for (String value : values) {
					listParam.addValue(value);
				}
				field.addParameter(listParam);
			} catch (NumberFormatException e) {
				isFloat = false;
			}

			if (!isFloat) {
				try {
					org.w3c.util.DateParser.parse(val);
					
					ListParameter listParam = new ListParameter("dateValue", SearchType.DATE, getOperator());
					for (String value : values) {
						listParam.addValue(value);
					}
					field.addParameter(listParam);
				} catch (NumberFormatException e) {
					isDate = false;
				} catch (InvalidDateException e) {
					isDate = false;
				}

				if (!isDate) {
					// its a string!!
					ListParameter listParam = new ListParameter("value", SearchType.STRING, getOperator());
					for (String value : values) {
						listParam.addValue(value);
					}
					field.addParameter(listParam);

					isString = true;
				}
			}
		}
		// this check is to make sure we also check the value column. this is
		// needed coz a user might define a custom field as a string in spec
		// view but then enter a date value in the data. that will be stored in
		// the value column and not in date column
		if (!isString) {
			ListParameter listParam = new ListParameter("value", SearchType.STRING, getOperator());
			for (String value : values) {
				listParam.addValue(value);
			}
			field.addParameter(listParam, false);
		}
	}

}
