package com.tandbergtv.spec;

import static com.tandbergtv.metadatamanager.model.FieldName.FILE_NAME;
import static com.tandbergtv.metadatamanager.model.FieldName.FILE_URL;
import static com.tandbergtv.metadatamanager.model.FieldName.MIME_TYPE;
import static com.tandbergtv.metadatamanager.model.FieldName.RESOLUTION;
import static com.tandbergtv.metadatamanager.model.FieldName.SIZE;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.tandbergtv.metadatamanager.ITTVDataModelHandler;
import com.tandbergtv.metadatamanager.exception.MetadataException;
import com.tandbergtv.metadatamanager.exception.SearchException;
import com.tandbergtv.metadatamanager.factoryImpl.SpecHandlerFactory;
import com.tandbergtv.metadatamanager.model.Asset;
import com.tandbergtv.metadatamanager.model.Field;
import com.tandbergtv.metadatamanager.model.FileType;
import com.tandbergtv.metadatamanager.model.Group;
import com.tandbergtv.metadatamanager.model.Item;
import com.tandbergtv.metadatamanager.model.Relation;
import com.tandbergtv.metadatamanager.model.RootAssetRevision;
import com.tandbergtv.metadatamanager.spec.IIdentifier;
import com.tandbergtv.metadatamanager.spec.ISpecHandler;
import com.tandbergtv.metadatamanager.specimpl.cl1_1.CL1_1_Identifier;
import com.tandbergtv.metadatamanager.specimpl.ttv.TTVId;
import com.tandbergtv.metadatamanager.util.Binder;

/**
 * Test class to verify Spec handler base.
 * 
 * @author spuranik
 * 
 */
public class TTVHandlerTest extends BaseHandlerTest {

	
	protected  String testFilePathAndName= "tests/com/tandbergtv/spec/sampleInput/convertedDoc";
	
	@Override
	protected ISpecHandler createSpecHandler() {
		ISpecHandler handler = (ISpecHandler) context
				.getBean("TTVSpecHandler");
		return handler;
	}
	
	protected ITTVDataModelHandler getTTVModelHandler() {
		ITTVDataModelHandler handler = (ITTVDataModelHandler) context
				.getBean("TTVSpecHandler");
		return handler;
	}

	protected ISpecHandler getCL11SpecHandler() {
		return SpecHandlerFactory.getInstance("CL1_1");
	}

	@Override
	protected String getSpecName() {
		return "TTV";
	}
	
	protected IIdentifier createIdentifier(){
		TTVId id = new TTVId();
		id.setSearchService(searchService);
		id.setId(1);
		return id;
	}
	
	public void _testPut(int fileIndexStart, int fileIndexEnd){
		putMutiple(testFilePathAndName, fileIndexStart, fileIndexEnd);
	}

	public void _testGetAssetByIdentifierAndRevision() {
		getAssetDocByIdentifierAndRevision(createIdentifier(), "." +2);
	}

	public void _testGetAllRevisionsByIdentifier(){
		getAllRevisionsByIdentifier(createIdentifier());
	}

	public void _testRollback(){
		rollback(1, "." +1);
	}

	
	public void _testPut_Rollback_GetAllRevisions(){
//		_testSaveAsset();
//		_testPut(1,1);
//		_testSaveAsset(1);
//		_testSaveAsset(2);
//		_testSaveAsset(3);
//		_testSaveAsset(4);
//		_testRollback();
		_testGetAllRevisionsByIdentifier();
	}
	
	public void _testDeleteUnique() {
		TTVId id = new TTVId();
		id.setId(191);
		id.setSearchService(searchService);
		ISpecHandler handler = createSpecHandler();
		try {
			handler.deleteUnique(id);
			System.out.println("Deleted asset with id: " + id.toString());
		} catch (SearchException e) {
			e.printStackTrace();
			fail();
		}
	}

	public void _testDeleteAll() {
		List<IIdentifier> ids = new ArrayList<IIdentifier>();

		TTVId id1 = new TTVId();
		id1.setId(192);
		id1.setSearchService(searchService);
		ids.add(id1);

		 TTVId id2 = new TTVId();
		 id2.setId(142);
		 id2.setSearchService(searchService);
		 ids.add(id2);

		ISpecHandler handler = createSpecHandler();
		List<IIdentifier> deletedIds = handler.deleteAll(ids);

		for (IIdentifier deletedId : deletedIds) {
			System.out
					.println("Deleted asset with id: " + deletedId.toString());
		}
	}
	
	public void _testGetAsset() {
		try {
			Asset a = getTTVModelHandler().getAsset(new TTVId(346));
			System.out.println(a.getVersion());
		} catch (SearchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}

	public void _testSaveDraftAsset() {
		ISpecHandler clhandler= getCL11SpecHandler();
		
		java.io.File file = new java.io.File ("tests/com/tandbergtv/spec/sampleInput/cl1_1-sample_1.xml");
		System.out.println("put file:" + file);
		DocumentBuilder builder = null;
		Document input = null;
		try {
			builder = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			input = builder.parse(file);
		} catch (SAXException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		} catch (ParserConfigurationException e2) {
			e2.printStackTrace();
		}
		
		List<Asset> mergedAssets = null;
		try {
			mergedAssets = clhandler.mergeWithoutSave(input);
		} catch (MetadataException e) {
			e.printStackTrace();
		}
		Asset mergedAsset = mergedAssets.get(0);
		
		ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory.getInstance("TTV");
		
		Asset a = null;
		try {
			a = ttvhandler.saveAsset(mergedAsset, true);
		} catch (MetadataException e) {
			e.printStackTrace();
		}

		System.out.println("Saved Asset with id: " + a.getId());
	}
	
	public void _testSaveAsset(String testFileName, int fileIndex)
			throws MetadataException {
		ITTVDataModelHandler handler = getTTVModelHandler();

		java.io.File  file = new java.io.File(testFileName + "_" + fileIndex
				+ textFileExtension);
		System.out.println("put file:" + file);
		DocumentBuilder builder = null;
		Document input = null;
		try {
			DocumentBuilderFactory builderFactory = DocumentBuilderFactory
					.newInstance();
			builderFactory.setNamespaceAware(true);
			builder = builderFactory.newDocumentBuilder();
			input = builder.parse(file);
		} catch (SAXException e1) {
			e1.printStackTrace();
			fail();
		} catch (IOException e1) {
			e1.printStackTrace();
			fail();
		} catch (ParserConfigurationException e2) {
			e2.printStackTrace();
			fail();
		}

		List<Asset> assets = new Binder().bind(input);
		for (Asset asset : assets) {
			handler.saveAsset(asset, "unit test", null,
					EXTERNAL_REVISION_TEST_EXTERNAL, false);
		}

	}
	
	public void _testBug3874(){
		boolean expectedExceptionThrown = false;
		String MetadataExceptionErrorMsg = "Multiple assets with spec Id";
		try{
		_testSaveAsset("tests/com/tandbergtv/spec/sampleInput/ttv_3874", 1);
		}catch( MetadataException ex){
			System.out.println(ex.getMessage());
			expectedExceptionThrown = ex.getMessage().contains(MetadataExceptionErrorMsg);
		}
		
		assertTrue("Expected MetadataException(" + MetadataExceptionErrorMsg + ") is not thrown.", expectedExceptionThrown);
	}
	
	public void _testSaveDraftAsset(String filePathAndName, int fileIndex) throws MetadataException {
		ISpecHandler clhandler = getCL11SpecHandler();

		java.io.File  file = new java.io.File(filePathAndName + "_" + fileIndex
				+ textFileExtension);
		System.out.println("put file:" + file);
		DocumentBuilder builder = null;
		Document input = null;
		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			input = builder.parse(file);
		} catch (SAXException e1) {
			e1.printStackTrace();
			fail();
		} catch (IOException e1) {
			e1.printStackTrace();
			fail();
		} catch (ParserConfigurationException e2) {
			e2.printStackTrace();
			fail();
		}

		List<Asset> mergedAssets = null;
		try {
			mergedAssets = clhandler.mergeWithoutSave(input);
		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		}
		Asset mergedAsset = mergedAssets.get(0);

		ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
				.getInstance("TTV");

		Asset a = ttvhandler.saveAsset(mergedAsset, true);

		System.out.println("Saved Asset with id: " + a.getId());
	}
	
	protected void saveDrafts(String filePathAndName, int fileIndexStart, int fileIndexEnd ) throws MetadataException{
		for(int i=fileIndexStart;i<=fileIndexEnd;i++){
			_testSaveDraftAsset(filePathAndName, i);
		}
	}
	
	public void _testBug3940(){
		try {
			saveDrafts("tests/com/tandbergtv/spec/sampleInput/cl1_3940", 1, 2);
		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		}
		
		ISpecHandler cl1SpecHandler = getCL11SpecHandler();
		CL1_1_Identifier id = (CL1_1_Identifier) cl1SpecHandler.getIdentifier();
		id.setAssetId("UNVA2001081701003000");
		id.setProviderId("3940");
		
		List<RootAssetRevision> revisions = getAllRevisionsByIdentifier(cl1SpecHandler, id);

		assertEquals(1, revisions.size());
		
		try{			
		
		ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
		.getInstance("TTV");
		
		Asset asset = ttvhandler.getAsset(id.getAssetTTVId());

		assertEquals("Package should only contains Titile, not Movie", 1, asset.getRelations().size());
		}catch(Exception ex){
			ex.printStackTrace();
			fail(ex.getMessage());
		}
		
	}
	
	
	public void _testBug4843() {
		try {
			_testSaveAsset("tests/com/tandbergtv/spec/sampleInput/ttv_4843", 1);
		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		}

		ISpecHandler cl1SpecHandler = getCL11SpecHandler();
		CL1_1_Identifier id = (CL1_1_Identifier) cl1SpecHandler.getIdentifier();
		id.setAssetId("UNVA2001081701003000");
		id.setProviderId("4843");

		
		try {
			// add File
			ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
					.getInstance("TTV");

			TTVId ttvid = id.getAssetTTVId();
			Asset asset = ttvhandler.getAsset(ttvid);

			for (Relation childRelation : asset.getRelations()) {
				Asset child = childRelation.getTargetAsset();
				if (child.getAssetType().equalsIgnoreCase(
						Item.ItemType.MOVIE.toString())) {
					Asset file = createfile(4843);

					child.addChild(file);
					break;
				}
			}

			ttvhandler.saveAsset(asset, false);
			System.out.println("after adding File");
			// delete File
			asset = ttvhandler.getAsset(ttvid);

			for (Relation childRelation : asset.getRelations()) {
				Asset child = childRelation.getTargetAsset();
				if (child.getAssetType().equalsIgnoreCase(
						Item.ItemType.MOVIE.toString())) {
					child.getRelations().clear();
					break;
				}
			}

			ttvhandler.saveAsset(asset, false);
			System.out.println("after deleting File");
			
			//checking result
			asset = ttvhandler.getAsset(ttvid);
			
			for (Relation childRelation : asset.getRelations()) {
				Asset child = childRelation.getTargetAsset();
				if (child.getAssetType().equalsIgnoreCase(
						Item.ItemType.MOVIE.toString())) {
					assertTrue("Move shouldn't contain any children after deleing the File", child.getRelations().size()==0);
					break;
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			fail(ex.getMessage());
		}
	}
	
	
	com.tandbergtv.metadatamanager.model.File createfile(int bugNumber) {
		com.tandbergtv.metadatamanager.model.File file = new com.tandbergtv.metadatamanager.model.File();
		
//		file.setType(ItemType.VIDEO);
		file.setFileType(FileType.ORIGINAL);
		
		file.addField(new Field(FILE_URL.toString(), "fileURL//"+ bugNumber));
		file.addField(new Field(FILE_NAME.toString(), "ChoLENy73wIaEQlbwqbpvT6ZzhMYDSANFEgGDA==/0/0/0/video.3gp"));
		file.addField(new Field(MIME_TYPE.toString(), "video/3gpp"));
		file.addField(new Field(RESOLUTION.toString(), "1920.0x1080.0"));
		file.addField(new Field(SIZE.toString(), "26010364"));
		
		return file;
	}
	
	public void testBug4514(){
		try {
			_testSaveAsset("tests/com/tandbergtv/spec/sampleInput/ttv_4514", 1);
		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		}
		
		try {
			saveDrafts("tests/com/tandbergtv/spec/sampleInput/cl1_4514", 1, 1);
		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		}
		
		ISpecHandler cl1SpecHandler = getCL11SpecHandler();
		CL1_1_Identifier id = (CL1_1_Identifier) cl1SpecHandler.getIdentifier();
		id.setAssetId("UNVA2001081701003000");
		id.setProviderId("4514");
		
		List<RootAssetRevision> revisions = getAllRevisionsByIdentifier(cl1SpecHandler, id);

		//non-draft to draft, the revision # should always bump up
		assertEquals(2, revisions.size());
		
		try{			
		
		ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
		.getInstance("TTV");
		
		Asset draftAsset = ttvhandler.getAsset(id.getAssetTTVId());

		RootAssetRevision existingRootAssetRevision = ((Group)draftAsset).getLatestRootAssetRevision();
		
		assertTrue("Latest revison should be DRAFT", existingRootAssetRevision.isDraft());
		
		//draft to non-draft, the revision # should always stay the same
		Asset nonDraftAsset = ttvhandler.saveAsset(draftAsset, false);
		
		revisions = getAllRevisionsByIdentifier(cl1SpecHandler, id);

		assertEquals(2, revisions.size());
		
		existingRootAssetRevision = ((Group)nonDraftAsset).getLatestRootAssetRevision();
		
		assertTrue("Latest revison should NOT be DRAFT", !existingRootAssetRevision.isDraft());
		}catch(Exception ex){
			ex.printStackTrace();
			fail(ex.getMessage());
		}
		
	}
	
	
	
	public void testBug4894(){
		try {
			_testSaveAsset("tests/com/tandbergtv/spec/sampleInput/ttv_4894", 1);
		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		}
		
		
		
		ISpecHandler cl1SpecHandler = getCL11SpecHandler();
		CL1_1_Identifier id = (CL1_1_Identifier) cl1SpecHandler.getIdentifier();
		id.setAssetId("UNVA2001081701003000");
		id.setProviderId("4894");
		
		try{			
		
		ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
		.getInstance("TTV");
		
		Asset asset = ttvhandler.getAsset(id.getAssetTTVId());

		Relation movieRelation = null;
		for (Relation childRelation : asset.getRelations()) {
			Asset child = childRelation.getTargetAsset();
			if (child.getAssetType().equalsIgnoreCase(
					Item.ItemType.MOVIE.toString())) {
				movieRelation = childRelation;
				break;
			}
		}
		
		asset.getRelations().remove(movieRelation);
		
		//delete the Movie asset 
		Asset assetAfterDeletion = ttvhandler.saveAsset(asset, false);

		assertEquals("After deleting the Movie from the package, there should be only one child left: Title.", 1, assetAfterDeletion.getRelations().size());
		
		}catch(Exception ex){
			ex.printStackTrace();
			fail(ex.getMessage());
		}
		
	}
	
	public void testBug5158() {
		ISpecHandler cl1SpecHandler = getCL11SpecHandler();
		CL1_1_Identifier id = (CL1_1_Identifier) cl1SpecHandler.getIdentifier();
		id.setAssetId("UNVA2001081701003000");
		id.setProviderId("5158");
		
		try {
			_testSaveAsset("tests/com/tandbergtv/spec/sampleInput/ttv_5158", 1);

			
			ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
			.getInstance("TTV");
			
			Asset asset = ttvhandler.getAsset(id.getAssetTTVId());
			for(Field field: asset.getFields()){
				if("5158_package_desc_init".equalsIgnoreCase(field.getValue())){
					field.setValue("5158_package_desc_02");
				}
			}
			
			ttvhandler.saveAsset(asset, "unit test", null,
					EXTERNAL_REVISION_TEST_EXTERNAL, false);

			saveDrafts("tests/com/tandbergtv/spec/sampleInput/cl1_5158", 1, 1);

			saveDrafts("tests/com/tandbergtv/spec/sampleInput/cl1_5158", 2, 2);

		} catch (MetadataException e) {
			e.printStackTrace();
			fail();
		} catch (SearchException e) {
			e.printStackTrace();
			fail();
		}
		

		Document doc = getAssetDocByIdentifierAndRevision(id, ".1");
		String docString = convertAssetDocToString(doc);
		System.out.println("in testBug5158, docString: " + docString);
		assertTrue("title.Title'value('5158_title_title_01') should be still existing in older version after saveDraft deleting, but it's not: \n ",  docString.contains("5158_title_title_01"));
	}
	
	
	public void testBug5214() {
		ISpecHandler cl1SpecHandler = getCL11SpecHandler();
		CL1_1_Identifier id = (CL1_1_Identifier) cl1SpecHandler.getIdentifier();
		id.setAssetId("UNVA2001081701003000");
		id.setProviderId("5214");
		
		try {
			_testSaveAsset("tests/com/tandbergtv/spec/sampleInput/ttv_5214", 1);

			saveDrafts("tests/com/tandbergtv/spec/sampleInput/cl1_5214", 1, 1);

			// add File
			ITTVDataModelHandler ttvhandler = (ITTVDataModelHandler) SpecHandlerFactory
					.getInstance("TTV");

			TTVId ttvid = id.getAssetTTVId();
			Asset asset = ttvhandler.getAsset(ttvid);

			for (Relation childRelation : asset.getRelations()) {
				Asset child = childRelation.getTargetAsset();
				if (child.getAssetType().equalsIgnoreCase(
						Item.ItemType.MOVIE.toString())) {
					Asset file = createfile(5214);

					child.addChild(file);
					break;
				}
			}

			ttvhandler.saveAsset(asset, true);
			System.out.println("after adding File");

		} catch (Exception e) {
			e.printStackTrace();
			fail();
		} 
		

		Document doc = getAssetDocByIdentifierAndRevision(id, ".1");
		String docString = convertAssetDocToString(doc);
		System.out.println("in testBug5214, docString: " + docString);
		assertTrue("File Item added during saveDraft should not show up in initial revision! ",  !docString.contains("fileURL//5214"));
	}
}
