package com.tandbergtv.metadata.test.search;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.tandbergtv.metadatamanager.model.Asset;
import com.tandbergtv.metadatamanager.search.AssetSearchKey;
import com.tandbergtv.metadatamanager.search.AssetSearchService;
import com.tandbergtv.metadatamanager.search.FieldInfo;
import com.tandbergtv.metadatamanager.search.LogicalOperator;
import com.tandbergtv.metadatamanager.search.MetadataValueFieldInfo;
import com.tandbergtv.metadatamanager.search.NodeFieldInfo;
import com.tandbergtv.metadatamanager.search.PropertyValueField;
import com.tandbergtv.metadatamanager.search.SearchField;
import com.tandbergtv.metadatamanager.search.SearchFieldList;
import com.tandbergtv.metadatamanager.search.SearchInfo;

public class MultipleConditionTest extends TestCase {

	private ApplicationContext context;

	@Override
	public void setUp() throws Exception {
		super.setUp();

		try {
			this.context = new ClassPathXmlApplicationContext(new String[] {
					"MetadataBeansContext.xml",
					"file:tests/MetadataManager_JTA_DBContext_UnitTest.xml",
					"file:tests/DataSource_UnitTest.xml" });
		} catch (Exception e) {
			System.out.print(e);
		}
	}

	@Override
	public void tearDown() throws Exception {
		super.tearDown();
	}
	
	public void test3ANDConditions() {
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		// major version greater than
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Version/tns:Major", LogicalOperator.GREATERTHAN, "2");
		field1.setAssetType("PACKAGE");
		fields.add(field1);
		
		// package asset id equals 'something'
		FieldInfo field2 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPPK0001177539262940");
		field2.setAssetType("PACKAGE");
		fields.add(field2);
		
		// title lisc start window date <= something
		FieldInfo field3 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Rights/tns:LicensingWindowStart", LogicalOperator.LESSTHAN, "2010-04-10");
		field3.setAssetType("TITLE");
		fields.add(field3);

		info.setFields(fields);

		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("1 AND 2 AND 3 conditions search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public void testORCondition() {
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		// package asset id equals 'something'
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPPK0001177539262940");
		field1.setAssetType("PACKAGE");
		fields.add(field1);
		
		// movie asset id = something
		FieldInfo field2 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPMV0000000000022413");
		field2.setAssetType("MOVIE");
		field2.setConjunction(false);
		fields.add(field2);

		info.setFields(fields);

		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("1 OR 2 condition search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public void testAndOrCondition() {
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		// package asset id equals 'something'
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPPK0001177539262940");
		field1.setAssetType("PACKAGE");
		fields.add(field1);
		
		// title lisc start window date <= something
		FieldInfo field2 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Rights/tns:LicensingWindowStart", LogicalOperator.LESSTHAN, "2010-04-10");
		field2.setAssetType("TITLE");
		fields.add(field2);
		
		// movie asset id = something
		FieldInfo field3 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPMV0001162508619393");
		field3.setAssetType("MOVIE");
		field3.setConjunction(false);
		fields.add(field3);

		info.setFields(fields);

		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("1 AND 2 OR 3 condition search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}	
	}
	
	public void testParenthesis() {
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		// package asset id equals 'something'
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPPK0001177539262940");
		field1.setAssetType("PACKAGE");
		fields.add(field1);
		
		NodeFieldInfo subList = new NodeFieldInfo();
		subList.setConjunction(false);
		subList.setChildrenConjunction(false);
		List<FieldInfo> subFields = new ArrayList<FieldInfo>();
		
		// title lisc start window date <= something
		FieldInfo field2 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Rights/tns:LicensingWindowEnd", LogicalOperator.LESSTHAN, "2010-04-10");
		field2.setAssetType("TITLE");
		subFields.add(field2);
		
		// movie asset id = something
		FieldInfo field3 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "test movie id");
		field3.setAssetType("MOVIE");
		subFields.add(field3);
		subList.setFields(subFields);

		fields.add(subList);
		info.setFields(fields);

		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("1 OR [2 OR 3] condition search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public void test3ORConditions() {
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		// major version greater than
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Version/tns:Major", LogicalOperator.GREATERTHAN, "2");
		field1.setAssetType("PACKAGE");
		fields.add(field1);
		
		// package asset id equals 'something'
		FieldInfo field2 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "hdpa2000000000001307");
		field2.setAssetType("PACKAGE");
		field2.setConjunction(false);
		fields.add(field2);
		
		// title lisc start window date <= something
		FieldInfo field3 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Rights/tns:LicensingWindowEnd", LogicalOperator.LESSTHAN, "2010-04-10");
		field3.setAssetType("TITLE");
		field3.setConjunction(false);
		fields.add(field3);

		info.setFields(fields);

		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("1 OR 2 OR 3 conditions search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public void testMultipleParenthesis() {
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		// package asset id equals 'something'
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPPK0001177539262940");
		field1.setAssetType("PACKAGE");
		fields.add(field1);
		
		NodeFieldInfo subList1 = new NodeFieldInfo();
		subList1.setConjunction(false);
		subList1.setChildrenConjunction(true);
		List<FieldInfo> subFields = new ArrayList<FieldInfo>();		
		// title lisc start window date <= something
		FieldInfo field2 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Rights/tns:LicensingWindowEnd", LogicalOperator.EQUAL, "2019-10-29");
		field2.setAssetType("TITLE");
		subFields.add(field2);		
		// movie asset id = something
		FieldInfo field3 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "test movie id");
		field3.setAssetType("MOVIE");
		subFields.add(field3);
		subList1.setFields(subFields);
		
		NodeFieldInfo subList2 = new NodeFieldInfo();
		subList2.setConjunction(false);
		subList2.setChildrenConjunction(true);
		List<FieldInfo> subFields2 = new ArrayList<FieldInfo>();		
		// title brief starts with something
		FieldInfo field4 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Title/tns:ShortTitle/tns:Value", LogicalOperator.STARTSWITH, "The");
		field4.setAssetType("TITLE");
		subFields2.add(field4);		
		// movie checksum = something
		FieldInfo field5 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Identifier/tns:Id", LogicalOperator.EQUAL, "XPMV0000000000022413");
		field5.setAssetType("MOVIE");
		subFields2.add(field5);
		subList2.setFields(subFields2);

		fields.add(subList1);
		fields.add(subList2);
		info.setFields(fields);

		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("1 OR [2 AND 3] OR [4 AND 5] condition search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public void testSubListWithProperty() {
		// [P1 AND/OR P2] AND/OR MD1
		SearchInfo info = new SearchInfo();
		List<SearchField> fields = new ArrayList<SearchField>();
		
		SearchFieldList sfl = new SearchFieldList();
		sfl.setConjunction(true);
		List<SearchField> subFields = new ArrayList<SearchField>();
		
		PropertyValueField p1 = new PropertyValueField();
		p1.setConjunction(true);
		p1.setEntityClass(Asset.class);
		p1.setName(AssetSearchKey.ASSET_TYPE.toString());
		p1.setOperator(LogicalOperator.ISEMPTY);
		List<String> values1 = new ArrayList<String>();
		values1.add("POSTER");
		p1.setValues(values1);
		subFields.add(p1);
		
		PropertyValueField p2 = new PropertyValueField();
		p2.setConjunction(false);
		p2.setEntityClass(Asset.class);
		p2.setName(AssetSearchKey.ASSET_TYPE.toString());
		p2.setOperator(LogicalOperator.ISEMPTY);
		List<String> values2 = new ArrayList<String>();
		values2.add("PREVIEW");
		p2.setValues(values2);
		subFields.add(p2);
		
		sfl.setSubFields(subFields);
		
		fields.add(sfl);
		
		// major version greater than
		FieldInfo field1 = new MetadataValueFieldInfo(
				"/tns:Fields/tns:Version/tns:Major", LogicalOperator.GREATERTHAN, "2");
		field1.setAssetType("PACKAGE");
		field1.setConjunction(true);
		fields.add(field1);		
		
		info.setFields(fields);
		try {
			AssetSearchService service = (AssetSearchService) context.getBean("assetSearch");
			String query = service.getQuery("searchResults", "sortResults", info, null);
			System.out.println("[P1 OR P2] AND MD1 condition search query: " + query);
		} catch (Exception e) {
			System.out.println(e);
		}
	}
}
