/**
 ********************************************************************************
 * Copyright (c) 2015-2020 Robert Bosch GmbH and others.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Robert Bosch GmbH - initial API and implementation
 ********************************************************************************
 */

package org.eclipse.app4mc.amalthea.converters071.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;

import org.eclipse.app4mc.amalthea.converters.common.ServiceConstants;
import org.eclipse.app4mc.amalthea.converters.common.base.ICache;
import org.eclipse.app4mc.amalthea.converters.common.utils.AmaltheaNamespaceRegistry;
import org.eclipse.app4mc.amalthea.converters.common.utils.HelperUtil;
import org.eclipse.app4mc.amalthea.converters.common.utils.ModelVersion;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(
		property = ServiceConstants.INPUT_MODEL_VERSION_PROPERTY + "=0.7.0")

public class SectionRunnableLabelCacheBuilder implements ICache {

	private static final Logger LOGGER = LoggerFactory.getLogger(SectionRunnableLabelCacheBuilder.class);

	private final HashMap<File, Map<String, Object>> map = new HashMap<>();

	@Override
	public void buildCache(final Map<File, Document> fileDocumentMapping) {

		LOGGER.info("Build up SectionRunnableLabelCache for 0.7.0");

		for (Entry<File, Document> entry : fileDocumentMapping.entrySet()) {
			final File targetFile = entry.getKey();
			final Document document1 = entry.getValue();
			
			if (document1 == null) {
				// log error message
				continue;
			}

			Element rootElement = document1.getRootElement();

			/*- Start : Cache initialization */

			Map<String, Object> fileCache = map.get(targetFile);
			if (fileCache == null) {
				fileCache = new HashMap<>();
				map.put(targetFile, fileCache);
			}

			HashMap<String, List<String>> label_Sections_Map = new HashMap<>();
			fileCache.put(SectionRunnableLabelCacheEnum.Label_Sections.name(), label_Sections_Map);

			HashMap<String, List<String>> runnable_Sections_Map = new HashMap<>();
			fileCache.put(SectionRunnableLabelCacheEnum.Runnable_Sections.name(), runnable_Sections_Map);

			ArrayList<String> section_Names = new ArrayList<>();
			fileCache.put(SectionRunnableLabelCacheEnum.Section_Names.name(), section_Names);

			/*-
			 * Note: Below two cache elements are used to support the models which are migrated from version 1.0.3/1.1.0 to the higher versions
			 */

			HashMap<String, List<String>> labelUUID_Sections = new HashMap<>();
			fileCache.put(SectionRunnableLabelCacheEnum.Label_UUID_Sections.name(), labelUUID_Sections);

			HashMap<String, List<String>> runnableUUID_Sections = new HashMap<>();
			fileCache.put(SectionRunnableLabelCacheEnum.Runnable_UUID_Sections.name(), runnableUUID_Sections);

			/*- End : Cache initialization */

			List<Element> sectionElements = HelperUtil.getXpathResult(
					rootElement,
					"./swModel/sections",
					Element.class,
					AmaltheaNamespaceRegistry.getNamespace(ModelVersion._070, "am"));

			for (final Element sectionElement : sectionElements) {

				final String sectionName = sectionElement.getAttributeValue("name");
				/*-adding section name in the cache */
				section_Names.add(sectionName);


				final Attribute labelsAttribute = sectionElement.getAttribute("labels");

				if (labelsAttribute != null) {
					extractMemoryElementSectionInfo(label_Sections_Map, sectionName, labelsAttribute,
							labelUUID_Sections);
				}

				final Attribute runEntitiesAttribute = sectionElement.getAttribute("runEntities");

				if (runEntitiesAttribute != null) {
					extractMemoryElementSectionInfo(runnable_Sections_Map, sectionName, runEntitiesAttribute,
							runnableUUID_Sections);
				}


				final List<Element> labelElements = sectionElement.getChildren("labels");

				for (final Element element : labelElements) {
					extractMemoryElementSectionInfo(label_Sections_Map, sectionName, element, labelUUID_Sections);
				}

				final List<Element> runnableElements = sectionElement.getChildren("runEntities");

				for (final Element element : runnableElements) {
					extractMemoryElementSectionInfo(runnable_Sections_Map, sectionName, element,
							runnableUUID_Sections);

				}
			}
		}
	}

	/**
	 * This method is used to populate the Label/Runnable name (i.e. MemoryElement name) and the corresponding Section
	 * names to which they are associated to
	 *
	 * @param memoryElement_Sections_Map
	 *            this map is part of the cache. Depending on type of the MemoryElement i.e. either Label or Runnable,
	 *            corresponding map is supplied to this method
	 * @param sectionName
	 *            Name of the section to which MemorElement (i.e. Label/Runnable) is associated to
	 * @param memoryElementAttribute
	 *            This the attribute of sections node (in amxmi). This can be either runEntities or labels attribute
	 *            <b>Note:</b> In case MemoryElements (Label/Runnable) which are defined in the same amxmi as the
	 *            section, then the corresponding references of label/runnable are generated inside labels/runEntities
	 *            attribute<br>
	 *            Example: <sections name="section6" labels="label6?type=Label" runEntities="Runnable7?type=Runnable"/>
	 * @param memMElementUUID_Sections
	 */
	private void extractMemoryElementSectionInfo(final Map<String, List<String>> memoryElement_Sections_Map,
			final String sectionName, final Attribute memoryElementAttribute,
			final Map<String, List<String>> memMElementUUID_Sections) {
		final String memoryElementAttributeValue = memoryElementAttribute.getValue();

		final StringTokenizer stk = new StringTokenizer(memoryElementAttributeValue);

		while (stk.hasMoreTokens()) {
			final String memoryElementReferenceString = stk.nextToken();

			final int lastIndexOf = memoryElementReferenceString.lastIndexOf('?');
			if (lastIndexOf != -1) {
				final String memoryElementName = memoryElementReferenceString.substring(0, lastIndexOf);

				addEntry(memoryElement_Sections_Map, memoryElementName, sectionName);
			}
			else {
				/*-
				 *  This is a case of UUID instead of AMALTHEA references
				 *  Example:
				 *  labels="_o_iL8JnJEeaK1-VgfUoZ4A _qHmnQJnJEeaK1-VgfUoZ4A"
				 */

				List<String> list = memMElementUUID_Sections.get(memoryElementReferenceString);

				if (list == null) {
					list = new ArrayList<>();
					memMElementUUID_Sections.put(memoryElementReferenceString, list);
				}
				list.add(sectionName);
			}
		}
	}

	/**
	 * This method is used to populate the Label/Runnable name (i.e. MemoryElement name) and the corresponding Section
	 * names to which they are associated to
	 *
	 * @param memoryElement_Sections_Map
	 *            this map is part of the cache. Depending on type of the MemoryElement i.e. either Label or Runnable,
	 *            corresponding map is supplied to this method
	 * @param sectionName
	 *            Name of the section to which MemorElement (i.e. Label/Runnable) is associated to
	 * @param memoryElement
	 *            This the Element of MemoryElement i.e either Label/Runnable. In amxmi this can be either runEntities
	 *            or labels element <b>Note:</b> In case MemoryElements (Label/Runnable) which are defined in the
	 *            different amxmi than the section, then the corresponding references of label/runnable are generated
	 *            inside labels/runEntities elements<br>
	 *            Example:<br>
	 *            <sections name="Section1"><br>
	 *            <labels href="amlt:/#label1?type=Label"/><br>
	 *            <labels href="amlt:/#label2?type=Label"/><br>
	 *            <labels href="amlt:/#label3?type=Label"/><br>
	 *            <runEntities href="amlt:/#Runnable1?type=Runnable"/><br>
	 *            <runEntities href="amlt:/#Runnable2?type=Runnable"/><br>
	 *            <runEntities href="amlt:/#Runnable3?type=Runnable"/><br>
	 *            </sections><br>
	 * @param memMElementUUID_Sections
	 */
	private void extractMemoryElementSectionInfo(final Map<String, List<String>> memoryElement_Sections_Map,
			final String sectionName, final Element memoryElement,
			final Map<String, List<String>> memElementUUID_Sections) {

		final String memoryElementAttributeValue = memoryElement.getAttributeValue("href");

		if (memoryElementAttributeValue != null) {

			final int indexOfHash = memoryElementAttributeValue.lastIndexOf('#');

			final int indexOfQuestionmark = memoryElementAttributeValue.lastIndexOf('?');

			if ((indexOfHash != -1) && (indexOfQuestionmark != -1)) {
				final String memroyElementName = memoryElementAttributeValue.substring(indexOfHash + 1,
						indexOfQuestionmark);

				addEntry(memoryElement_Sections_Map, memroyElementName, sectionName);
			}
			else if (indexOfHash != -1) {
				/*-
				 *  This is a case of UUID instead of AMALTHEA references
				 *  Example:
				 *  <sections xmi:id="_rcL0kJnJEeaK1-VgfUoZ4A" name="s1" >
				 *		<labels href="#_o_iL8JnJEeaK1-VgfUoZ4A"/>
				 *		<labels href="#_qHmnQJnJEeaK1-VgfUoZ4A"/>
				 *		<labels href="default1.amxmi#_fjEtAJnTEeaK1-VgfUoZ4A "/>
				 *	</sections>
				 */

				final String memoryElementID = memoryElementAttributeValue.substring(indexOfHash + 1);

				List<String> list = memElementUUID_Sections.get(memoryElementID);

				if (list == null) {
					list = new ArrayList<>();
					memElementUUID_Sections.put(memoryElementID, list);
				}

				list.add(sectionName);
			}
		}

	}

	/*- Add a entry  */

	private void addEntry(final Map<String, List<String>> memoryElement_Sections_Map, final String memoryElementName,
			final String sectionName) {

		if (!memoryElement_Sections_Map.containsKey(memoryElementName)) {

			memoryElement_Sections_Map.put(memoryElementName, new ArrayList<>());
		}
		memoryElement_Sections_Map.get(memoryElementName).add(sectionName);

	}

	@Override
	public Map<File, Map<String, Object>> getCacheMap() {
		return this.map;
	}

	@Override
	public void clearCacheMap() {
		this.map.clear();
	}

}
