/**
 * AssetSearch.java
 * Created Feb 5, 2009
 * Copyright (c) Tandberg Television 2009
 */
package com.tandbergtv.metadata.test.search;

import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRED;

import java.util.ArrayList;
import java.util.Collection;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.tandbergtv.metadatamanager.model.Asset;
import com.tandbergtv.metadatamanager.model.Field;
import com.tandbergtv.metadatamanager.model.ParentChildRelation;
import com.tandbergtv.metadatamanager.model.Relation;
import com.tandbergtv.metadatamanager.search.AssetSearchService;
import com.tandbergtv.watchpoint.search.Entity;
import com.tandbergtv.workflow.driver.search.SearchOperator;
import com.tandbergtv.workflow.driver.search.SearchType;
import com.tandbergtv.workflow.driver.search.ValueParameter;
import com.tandbergtv.workflow.util.SearchCriteria;

/**
 * @author Sahil Verma
 */
public class AssetSearch {
	
	private ApplicationContext context;

	private static final Logger logger = Logger.getLogger(AssetSearch.class);
	
	AssetSearch() {
		this.context = new ClassPathXmlApplicationContext(
				new String[] { "MetadataBeansContext.xml",
						"MetadataManagerDBContext.xml",
						"file:tests/DataSource_UnitTest.xml" });
	}
	
	AssetSearchService getSearchService() {
		AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
		
		return service;
	}
	
	void printAsset(Asset asset) {
		int children = 0;
		
		for (Relation relation : asset.getRelations())
			if (relation instanceof ParentChildRelation && asset.equals(relation.getOwnerAsset()))
				children++;
		
		logger.info(asset.getId() + ", " + children + " kid(s)");
		
		for (Field field : asset.getFields()) {
			logger.info("\t" + field.getTtvXPath() + ", " + field.getValue());
		}
	}
	
	Collection<Asset> getAssets() {
		AssetSearchService service = getSearchService();
		SearchCriteria criteria = getDefaultCriteria();
		
		//addDescendantFieldCriteria(criteria);
		//addRootAssetCriteria(criteria);
		//addChildAssetCriteria(criteria);
		addFieldCriteriaOR(criteria);
		
		// not supported any more!!
		// Collection<Asset> assets = service.search(criteria);
		Collection<Asset> assets = new ArrayList<Asset>();
		
		for (Asset asset : assets)
			printAsset(asset);
		
		// logger.info("Count " + service.count(criteria));
		
		return assets;
	}
	
	void addRootAssetCriteria(SearchCriteria criteria) {
		Entity asset = criteria.getParameter("asset", Entity.class);
		
		asset.addParameter(new ValueParameter("root", SearchType.NUMERIC, (Object) null));
		//Status?
	}
	
	void addChildAssetCriteria(SearchCriteria criteria) {
		Entity asset = criteria.getParameter("asset", Entity.class);
		
		asset.addParameter(new ValueParameter("root", SearchType.NUMERIC, (Object) null, SearchOperator.NOTEQUAL));
	}
	
	void addDescendantFieldCriteria(SearchCriteria criteria) {
		Entity asset = criteria.getParameter("asset", Entity.class);
		Entity field = new Entity("field", "allDescendantAssetFields", "f");
		
		field.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, "abc", SearchOperator.LIKE));
		field.addParameter(new ValueParameter("value", SearchType.STRING, "c"));
		
		asset.addParameter(field);
	}
	
	void addFieldCriteria(SearchCriteria criteria) {
		Entity asset = criteria.getParameter("asset", Entity.class);
		Entity field = new Entity("field", "fields", "f");
		
		field.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, "/tns:Fields/tns:AssetClass", SearchOperator.LIKE));
		field.addParameter(new ValueParameter("value", SearchType.STRING, "package"));
		
		asset.addParameter(field);
	}
	
	void addFieldCriteriaOR(SearchCriteria criteria) {
		Entity asset = criteria.getParameter("asset", Entity.class);
		Entity field = new Entity("field", "fields", "f");
		
/*		field.addParameter(new ValueParameter("value", SearchType.STRING, "Captain Corellis Mandolin title", SearchOperator.LIKE));
		field.addParameter(new ValueParameter("value", SearchType.STRING, "package"), true);
		
		asset.addParameter(field);
*/		
		field.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, "/tns:Fields/tns:AssetClass", SearchOperator.LIKE));
		field.addParameter(new ValueParameter("value", SearchType.STRING, "package"));

		
		Entity field1 = new Entity("field", "fields", "f");

		field1.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, "/tns:Fields/tns:AssetName", SearchOperator.LIKE));
		field1.addParameter(new ValueParameter("value", SearchType.STRING, "CaptainCorellisMandolinpackage"));
		
		Entity field2 = new Entity("field", "fields", "f");

		field2.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, "/tns:Fields/tns:AssetClass", SearchOperator.LIKE));
		field2.addParameter(new ValueParameter("value", SearchType.STRING, "title"));

		Entity field3 = new Entity("field", "fields", "f");

		field3.addParameter(new ValueParameter("ttvXPath", SearchType.STRING, "/tns:Fields/tns:AssetName", SearchOperator.LIKE));
		field3.addParameter(new ValueParameter("value", SearchType.STRING, "Captain Corellis Mandolin title"));

		
		asset.addParameter(field);
		asset.addParameter(field1);
		asset.addParameter(field2, false);
		asset.addParameter(field3);
	}
	
	SearchCriteria getDefaultCriteria() {
		SearchCriteria criteria = new SearchCriteria();
		
		Entity asset = new Entity("asset", Asset.class, "a");
		
		//asset.addParameter(new SortParameter("id", SortingOrder.DESCENDING));
/*		Entity e = new Entity("fieldsort", "fields", "sf");
		
		e.setJoin(Join.LEFT_OUTER);
		e.setFetch(true);
		e.addParameter(new ValueParameter("ttvXPath", STRING, "/tns:Fields/tns:AssetClass", SearchOperator.LIKE));
		e.addParameter(new SortParameter("value", SortingOrder.ASCENDING));
		
		asset.addParameter(e);*/
		
		criteria.addParameter(asset);
		criteria.setRecordsCount(Integer.MAX_VALUE);
		
		return criteria;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AssetSearch t = new AssetSearch();
		
		try {
			PlatformTransactionManager txmgr = 
				(PlatformTransactionManager) t.context.getBean("transactionManager");
			TransactionStatus status = 
				txmgr.getTransaction(new DefaultTransactionDefinition(PROPAGATION_REQUIRED));
			
			t.getAssets();
			
			txmgr.commit(status);
		} catch (Throwable e) {
			logger.error("Damn!", e);
		}
	}
}
