/**
 * Petals View - Functional Supervision.
 * Copyright (c) 2010 EBM Websourcing, http://www.ebmwebsourcing.com/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -------------------------------------------------------------------------
 * CreationScript.java
 * -------------------------------------------------------------------------
 */
package com.ebmwebsourcing.petalsview.service.notification;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import com.ebmwebsourcing.petalsview.service.CommonServiceConfig;

@RunWith(SpringJUnit4ClassRunner.class)
public class CreationScript extends CommonServiceConfig {

	private NotificationReader notifPersistence;

	private static int NUMBER_INSERT = 5000;
	private static int NUMBER_Start = 4000;
	
	@Resource
	private NotificationProcessor notificationProcessor;

	@Test
	@Rollback(value = false)
	public void inject() {

		// System.setProperty("hibernate.default.config",
		// "file:///home/strino/Bureau/hibernate.cfg.xml");

		notifPersistence = new NotificationReader();

		requestFlowStartDate();
		requestFlowEndDate();
	}

	public void requestFlowStartDate() {

		String idName;
		int status;
		int type;
		int numberInsert = NUMBER_INSERT;
		int numberStart = NUMBER_Start;
		Date startDate = new Date();
		Calendar cal = GregorianCalendar.getInstance();
		cal.add(Calendar.DATE, 0);
		startDate = cal.getTime();

		int i;
		// Création des Flow de type 1
		for (i = numberStart; i < numberInsert + numberStart; i++) {
			idName = "test:test" + i;
			status = -1;
			type = 1;

			int numberStep = 4;

			// Création des étapes ici 4
			for (int l = 0; l < numberStep; l++) {
				// Création des informations pour l'étape 1
				if (l == 0) {
					getInformationFlowOneStepOne(idName, status, type,
							startDate, i, l);
				}
				// Création des information pour l'étape 2
				if (l == 1) {
					getInformationFlowOneStepTwo(idName, status, type,
							startDate, i, l);

				}
				// Création des information pour l'étape 3
				if (l == 2) {
					getInformationFlowOneStepThree(idName, status, type,
							startDate, i, l);

				}
				// Création des information pour l'étape 4
				if (l == 3) {
					getInformationFlowOneStepFour(idName, status, type,
							startDate, i, l);
				}
			}
		}

		// Création des Flow de type 2
//		status = -1;
//		i = createFlowTypeTwo(numberInsert, status, startDate, i);

		// création des Flow de type 3
//		i = createFlowTypeThree(numberInsert, status, startDate, i);
	}

	public void requestFlowEndDate() {

		String idName;
		int status;
		int type;
		int numberInsert = NUMBER_INSERT;
		int numberStart = NUMBER_Start;
		Date endDate = new Date();
		Calendar cal = GregorianCalendar.getInstance();
		cal.add(Calendar.DATE, 0);
		endDate = cal.getTime();

		int i;
		// Création des Flow de type 1
		for (i = numberStart; i < numberInsert + numberStart; i++) {
			idName = "test:test" + i;
			status = 0;
			type = 1;

			int numberStep = 4;

			// Création des étapes ici 4
			for (int l = 0; l < numberStep; l++) {
				// Création des informations pour l'étape 1
				if (l == 0) {

					status = 0;
					getInformationFlowOneStepOne(idName, status, type, endDate,
							i, l);
				}
				// Création des information pour l'étape 2
				if (l == 1) {

					status = 1;
					getInformationFlowOneStepTwo(idName, status, type, endDate,
							i, l);
				}
				// Création des information pour l'étape 3
				if (l == 2) {

					status = 0;
					getInformationFlowOneStepThree(idName, status, type,
							endDate, i, l);
				}
				// Création des information pour l'étape 4
				if (l == 3) {

					status = 0;
					getInformationFlowOneStepFour(idName, status, type,
							endDate, i, l);
				}
			}
		}

		// Création des Flow de type 2
//		status = 0;
//		i = createFlowTypeTwo(numberInsert, status, endDate, i);

		// création des Flow de type 3
//		i = createFlowTypeThree(numberInsert, status, endDate, i);
	}

	private void getInformationFlowOneStepOne(String idName, int status,
			int type, Date date, int i, int l) {
		String endpointName = "endpoint1";
		String interfaceName = "interface1";
		String serviceName = "service1";
		String increment = String.valueOf(i);
		String meUUID = "012011" + increment;

		// Définition du nombre de paramètres pour l'étape 1
		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 4; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		// envoie des informations dans la méthode qui simule une notification
		// en générant le fichier xml.
		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);

	}

	private void getInformationFlowOneStepTwo(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint2";
		String interfaceName = "interface2";
		String serviceName = "service2";
		String meUUID = "012012" + i;
		// int errorcode = 0;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 3; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void getInformationFlowOneStepThree(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint3";
		String interfaceName = "interface3";
		String serviceName = "service3";
		String meUUID = "012013" + i;
		// int errorcode = 0;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 2; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);

	}

	private void getInformationFlowOneStepFour(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint4";
		String interfaceName = "interface4";
		String serviceName = "service4";
		String meUUID = "012014" + i;
		// int errorcode = 0;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 2; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	@SuppressWarnings("unused")
	private int createFlowTypeTwo(int numberInsert, int status, Date date, int i) {
		String idName;
		// int status;
		int type;
		int numberStart;
		numberStart = i;

		for (i = numberStart; i < numberInsert + numberStart; i++) {
			idName = "test:test" + i;
			// status = 0;
			type = 2;

			int numberStep = 3;
			// Création des étapes ici 3
			for (int l = 0; l < numberStep; l++) {
				// Création des information pour l'étape 1
				if (l == 0) {
					// status = -1;
					getInformationFlowTwoStepOne(idName, status, type, date, i,
							l);
				}
				// Création des information pour l'étape 2
				if (l == 1) {
					getInformationFlowTwoStepTwo(idName, status, type, date, i,
							l);
				}
				// Création des information pour l'étape 3
				if (l == 2) {
					getInformationFlowTwoStepThree(idName, status, type, date,
							i, l);
				}
			}
		}
		return i;
	}

	private void getInformationFlowTwoStepOne(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint11";
		String interfaceName = "interface11";
		String serviceName = "service11";
		String meUUID = "012021" + i;
		// int errorcode = 0;
		// status = -1;
		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 5; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void getInformationFlowTwoStepTwo(String idName, int status,
			int type, Date date, int i, int l) {
		String endpointName = "endpoint22";
		String interfaceName = "interface22";
		String serviceName = "service22";
		String meUUID = "012022" + i;
		// int errorcode = 0;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 2; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void getInformationFlowTwoStepThree(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint33";
		String interfaceName = "interface33";
		String serviceName = "service33";
		String meUUID = "012023" + i;
		// int errorcode = 0;

		// status = -1;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 3; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	@SuppressWarnings("unused")
	private int createFlowTypeThree(int numberInsert, int status, Date date,
			int i) {
		String idName;
		// int status;
		int type;
		int numberStart;
		numberStart = i;

		for (i = numberStart; i < numberInsert + numberStart; i++) {
			idName = "test:test" + i;
			// status = 1;
			type = 3;

			int numberStep = 4;
			// Création des étapes ici 4
			for (int l = 0; l < numberStep; l++) {
				// Création des information pour l'étape 1
				if (l == 0) {
					getInformationFlowThreeStepOne(idName, status, type, date,
							i, l);
				}
				// Création des information pour l'étape 2
				if (l == 1) {
					getInformationFlowThreeStepTwo(idName, status, type, date,
							i, l);
				}
				// Création des information pour l'étape 3
				if (l == 2) {
					getInformationFlowThreeStepThree(idName, status, type,
							date, i, l);
				}
				// Création des information pour l'étape 4
				if (l == 3) {
					getInformationFlowThreeStepFour(idName, status, type, date,
							i, l);
				}
			}

		}
		return i;
	}

	private void getInformationFlowThreeStepOne(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint:endpoint:endpoint111";
		String interfaceName = "interface:interface:interface111";
		String serviceName = "service:service:service:service111";
		String meUUID = "012031" + i;
		// int errorcode = 0;

		// status = -1;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 3; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void getInformationFlowThreeStepTwo(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint222";
		String interfaceName = "interface222";
		String serviceName = "service222";
		String meUUID = "012032" + i;
		// int errorcode = 0;

		// status = -1;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 3; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void getInformationFlowThreeStepThree(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint333";
		String interfaceName = "interface333";
		String serviceName = "service3";
		String meUUID = "012033" + i;
		// int errorcode = 0;

		// status = -1;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 2; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void getInformationFlowThreeStepFour(String idName, int status,
			int type, Date date, int i, int l) {

		String endpointName = "endpoint444";
		String interfaceName = "interface444";
		String serviceName = "service444";
		String meUUID = "012034" + i;
		// int errorcode = 0;

		// status = -1;

		List<String> params = new ArrayList<String>();

		for (int m = 1; m < 4; m++) {
			String param = "param" + m + l + i;
			params.add(param);
		}

		String processType = String.valueOf(type);
		String statusF = String.valueOf(status);
		String dateJ = String.valueOf(date.getTime());

		testWithNotificationInjection(idName, processType, interfaceName,
				serviceName, endpointName, meUUID, statusF, dateJ, params);
	}

	private void testWithNotificationInjection(String processPath,
			String processType, String interfaceName, String serviceName,
			String endpoint, String meuuids, String status, String date,
			List<String> params) {
		try {
			// We need a Document
			DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
			Document doc = docBuilder.newDocument();

			// //////////////////////
			// Creating the XML tree
			// create the root element and add it to the document
			Element root = doc
					.createElementNS(
							"http://www.ebmwebsourcing.com/WS-BaseNotification/NotifyContent",
							"NotifyContent");
			root.setPrefix("wsnebm");

			root.setAttribute("processPath", processPath);
			root.setAttribute("processType", processType);
			root.setAttribute("interface", interfaceName);
			root.setAttribute("service", serviceName);
			root.setAttribute("endpoint", endpoint);
			root.setAttribute("meuuid", meuuids);
			root.setAttribute("status", status);
			root.setAttribute("notifDate", date);

			doc.appendChild(root);

			// create child element, add an attribute, and add to root
			Element childParams = doc
					.createElementNS(
							"http://www.ebmwebsourcing.com/WS-BaseNotification/NotifyContent",
							"params");
			childParams.setPrefix(root.getPrefix());
			root.appendChild(childParams);

			for (int i = 0; i < params.size(); i++) {
				Element childParam = doc
						.createElementNS(
								"http://www.ebmwebsourcing.com/WS-BaseNotification/NotifyContent",
								"param");
				childParam.setPrefix(root.getPrefix());

				Text text = doc.createTextNode(params.get(i));
				childParam.appendChild(text);
				childParams.appendChild(childParam);
			}

			// ---------------------------------------------
			Document topicAsDoc = docBuilder.newDocument();
			Element rootTop = topicAsDoc.createElementNS(
					"http://docs.oasis-open.org/wsn/b-2", "TopicExpression");
			rootTop.setPrefix("wsnt");
			rootTop
					.setAttribute("Dialect",
							"http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple");
			Text textTopExpr = topicAsDoc
					.createTextNode("tns1:aSimpleRootTopic/childTopic1");
			rootTop.appendChild(textTopExpr);

			topicAsDoc.appendChild(rootTop);
			// -----------------------------------------------

			final javax.xml.transform.Source notifContentAsXmlSource = new DOMSource(
					doc);
			final javax.xml.transform.Source topicExpressionAsXmlSource = new DOMSource(
					topicAsDoc);

			// ///////////////
			// Output the XML

			// set up a transformer
			TransformerFactory transfac = TransformerFactory.newInstance();
			Transformer trans = transfac.newTransformer();
			trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
			trans.setOutputProperty(OutputKeys.INDENT, "yes");

			// create string from xml tree
			StringWriter sw1 = new StringWriter();
			StreamResult result1 = new StreamResult(sw1);

			// DOMSource source = new DOMSource(doc);

			trans.transform(notifContentAsXmlSource, result1);
			// String xmlString = sw1.toString();
			// print xml
			// System.out.println("Here's the NotifContent xml:\n\n" +
			// xmlString);

			// create string from xml tree
			StringWriter sw2 = new StringWriter();
			StreamResult result2 = new StreamResult(sw2);

			// DOMSource source = new DOMSource(doc);

			trans.transform(topicExpressionAsXmlSource, result2);
			// String xmlString = sw2.toString();
			// System.out.println("Here's the topicExpression xml:\n\n" +
			// xmlString);

			// notifPersistence.readNotification(topicExpressionAsXmlSource,
			// notifContentAsXmlSource);

			Notification n = notifPersistence.read(notifContentAsXmlSource);

			List<Notification> l = new ArrayList<Notification>();

			l.add(n);
			notificationProcessor.process(l);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
