package com.tandbergtv.config;

import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRED;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import junit.framework.TestCase;

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 org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.tandbergtv.metadatamanager.JPFActivator;
import com.tandbergtv.metadatamanager.MetadataManagerDAO;
import com.tandbergtv.metadatamanager.conf.SpecificationBuilder;
import com.tandbergtv.metadatamanager.exception.SearchException;
import com.tandbergtv.metadatamanager.factoryImpl.SpecHandlerFactory;
import com.tandbergtv.metadatamanager.model.Asset;
import com.tandbergtv.metadatamanager.model.Spec;
import com.tandbergtv.metadatamanager.spec.ISpecHandler;
import com.tandbergtv.metadatamanager.spec.IValidator;
import com.tandbergtv.metadatamanager.specimpl.ttv.TTVId;
import com.tandbergtv.metadatamanager.validation.ValidationError;

/**
 * Test class to verify if the spring config loads fine.
 * 
 * @author spuranik
 * 
 */
public class AppContextTest extends TestCase {

	private static final String JPF_PLUGIN_REPOSITORY_PROPERTY = "org.java.plugin.boot.pluginsRepositories";
	
	public void testContextLoad() {
		
		ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
				"MetadataBeansContext.xml",
				"MetadataManagerDBContext.xml",
				"file:tests/DataSource_UnitTest.xml" });

		MetadataManagerDAO impl = (MetadataManagerDAO) context
				.getBean("metadataManagerDAOImpl");
		try {
			PlatformTransactionManager txMgr = (PlatformTransactionManager) context
					.getBean("transactionManager");
			TransactionStatus status = 
				txMgr.getTransaction(new DefaultTransactionDefinition(PROPAGATION_REQUIRED));

			Asset a = impl.getAsset(new TTVId(67), true, true);

			System.out.println("Retrieved asset id[" + a.getTTVId().getId()
					+ "] in [" + a.getState() + "] state.");
			System.out.println("Asset has " + a.getRelations().size()
					+ " targets.");
			txMgr.commit(status);
		} catch (SearchException e) {
			e.printStackTrace();
		}
	}

	public void testHandlerLoad() {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				new String[] { "MetadataBeansContext.xml",
						"MetadataManagerDBContext.xml",
						"file:tests/DataSource_UnitTest.xml" });

		startJPF(context);
		
		ISpecHandler mstvHandler = SpecHandlerFactory.getInstance(Spec.MSTV.toString());
		System.out.println("Handler class: " + mstvHandler.getClass());

		ISpecHandler ttvHandler = SpecHandlerFactory.getInstance(Spec.TTV.toString());
		System.out.println("Handler class: " + ttvHandler.getClass());

		ISpecHandler cl1_1Handler = SpecHandlerFactory.getInstance(Spec.CL1_1.toString());
		System.out.println("Handler class: " + cl1_1Handler.getClass());
	}

	public void testValidator() {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				new String[] { "MetadataBeansContext.xml",
						"MetadataManagerDBContext.xml",
						"file:tests/DataSource_UnitTest.xml" });

		startJPF(context);
		
		ISpecHandler mstvHandler = SpecHandlerFactory.getInstance(Spec.MSTV.toString());

		Map<String, IValidator> validators = mstvHandler.getRuleValidators();
		IValidator validator;
		Iterator<Entry<String, IValidator>> validatorIter = validators
				.entrySet().iterator();
		if (validatorIter.hasNext()) {
			validator = validatorIter.next().getValue();
		} else {
			throw new RuntimeException("Validator not found");
		}

		
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		Document doc;
		try {
			builder = factory.newDocumentBuilder();
			doc = builder.parse(new File(
					"tests/com/tandbergtv/validation/input.xml"));
			List<ValidationError> errors = validator.validate(doc);
			for (ValidationError error : errors) {
				System.out.print(error.getErrorCode() + "-"
						+ error.getErrorLocation());
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void startJPF(ApplicationContext context) {
		Properties properties = new Properties();
		String installFolder = "/opt/tandbergtv/cms/plugins";

		properties.put(JPF_PLUGIN_REPOSITORY_PROPERTY, installFolder);

		
		JPFActivator activator = new JPFActivator();
		activator.start(properties);
		
		SpecificationBuilder builder = new SpecificationBuilder(activator.getPluginManager(), context);
		
		builder.buildSpecifications();
	}
}
