/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.oodt.cas.workflow.gui.model.repo;

//OODT imports
import org.apache.oodt.cas.metadata.Metadata;
import org.apache.oodt.cas.workflow.gui.model.ModelGraph;
import org.apache.oodt.cas.workflow.gui.model.ModelNode;
import org.apache.oodt.commons.xml.XMLUtils;

//JDK imports
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 
 * Model Repository which stores models in xml files
 * 
 * @author bfoster
 * @author mattmann
 * 
 */
public class XmlWorkflowModelRepository {

  private File workspace;
  private List<File> files;
  private Set<ModelGraph> graphs;
  private Map<String, ConfigGroup> globalConfigGroups;
  private static final Logger LOG = Logger
      .getLogger(XmlWorkflowModelRepository.class.getName());

  public XmlWorkflowModelRepository(File workspace) {
    this.files = new Vector<File>();
    for (File file : (this.workspace = workspace).listFiles())
      if (!file.isDirectory())
        this.files.add(file);
  }

  public void loadGraphs(Set<String> supportedProcessorIds) throws Exception {
    this.graphs = new HashSet<ModelGraph>();
    HashMap<String, ConfigGroup> globalConfGroups = new HashMap<String, ConfigGroup>();
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    DocumentBuilder parser = factory.newDocumentBuilder();
    List<FileBasedElement> rootElements = new Vector<FileBasedElement>();
    for (File file : files) {
      System.out.println("Loading: " + file);
      rootElements.add(new FileBasedElement(file, parser.parse(file)
          .getDocumentElement()));
    }
    for (FileBasedElement root : rootElements) {
      loadConfiguration(rootElements, root, null, globalConfGroups);
      NodeList rootChildren = root.getElement().getChildNodes();
      for (int i = 0; i < rootChildren.getLength(); i++)
        if (rootChildren.item(i).getNodeType() == Node.ELEMENT_NODE
            && !rootChildren.item(i).getNodeName().equals("configuration")
            && !rootChildren.item(i).getNodeName().equals("event")) {
          System.out.println("node name: ["
              + rootChildren.item(i).getNodeName() + "]");
          ModelGraph graph = this.loadGraph(rootElements, new FileBasedElement(
              root.getFile(), (Element) rootChildren.item(i)), new Metadata(),
              globalConfGroups, supportedProcessorIds);
          this.graphs.add(graph);
        }
    }
    ensureUniqueIds(graphs);
    this.globalConfigGroups = globalConfGroups;
    System.out.println(this.globalConfigGroups.keySet());
  }

  public Set<ModelGraph> getGraphs() {
    return this.graphs;
  }

  public Map<String, ConfigGroup> getGlobalConfigGroups() {
    return this.globalConfigGroups;
  }

  public void setGlobalConfigGroups(Map<String, ConfigGroup> globalConfigGroups) {
    this.globalConfigGroups = new HashMap<String, ConfigGroup>(
        globalConfigGroups);
  }

  public List<File> getFiles() {
    return this.files;
  }

  public void save() throws Exception {
    this.backupCurrentFiles();
    this.saveGraphs();
  }

  private void backupCurrentFiles() throws Exception {
    File backupDir = new File(this.workspace, ".backup");
    for (File file : this.files) {
      FileUtils.copyFile(file, new File(backupDir, file.getName()));
      file.delete();
    }
    this.files.clear();
  }

  private void saveGraphs() throws FileNotFoundException,
      ParserConfigurationException {
    Map<File, Document> documents = new HashMap<File, Document>();
    for (ModelGraph graph : this.graphs) {
      Document document = documents.get(graph.getModel().getFile());
      if (document == null) {
        document = createDocument();
        document.appendChild(document.createElement("workflows"));
        documents.put(graph.getModel().getFile(), document);
      }
      saveGraph(graph, document.getDocumentElement(), document);
    }
    saveGlobalConfigGroups(documents);
    writeOutDocuments(documents);
    this.files = new ArrayList<File>(documents.keySet());
  }

  private void writeOutDocuments(Map<File, Document> documents) {
    for (File file : documents.keySet()) {
      XMLUtils.writeXmlFile(documents.get(file), file.getAbsolutePath());
    }
  }

  private void saveGlobalConfigGroups(Map<File, Document> documents)
      throws ParserConfigurationException {
    File globalConfigGroupsFile = new File(workspace,
        "shared-configuration.xml");
    Document document = documents.get(globalConfigGroupsFile);
    if (document == null) {
      document = createDocument();
      document.appendChild(document.createElement("workflows"));
      documents.put(globalConfigGroupsFile, document);
    }
    for (String configName : this.globalConfigGroups.keySet()) {
      ConfigGroup globalConfig = this.globalConfigGroups.get(configName);
      Element configElem = document.createElement("configuration");
      document.getDocumentElement().appendChild(configElem);
      configElem.setAttribute("name", globalConfig.getName());
      if (!globalConfig.getExtends().isEmpty()) {
        configElem.setAttribute("extends",
            StringUtils.join(globalConfig.getExtends(), ", "));
      }

      String[] properties = globalConfig.getMetadata().getAllKeys()
          .toArray(new String[globalConfig.getMetadata().getAllKeys().size()]);
      Arrays.sort(properties);
      for (String property : properties) {
        Element propElem = document.createElement("property");
        configElem.appendChild(propElem);
        propElem.setAttribute("name", property);
        propElem.setAttribute("value",
            globalConfig.getMetadata().getMetadata(property));
      }
    }
  }

  private void saveGraph(ModelGraph graph, Element parentElem, Document document)
      throws FileNotFoundException, ParserConfigurationException {
    ModelNode node = graph.getModel();

    Element workflowElem = document.createElement(node.getExecutionType());
    parentElem.appendChild(workflowElem);

    if (node.isRef()) {
      workflowElem.setAttribute("id-ref", node.getModelId());
      if (node.getAlias() != null) {
        workflowElem.setAttribute("alias", node.getAlias());
      }
      saveConfiguration(node, workflowElem, document);
    } else {
      workflowElem.setAttribute("id", node.getModelId());
      workflowElem.setAttribute("name", node.getModelName());
      if (node.getInstanceClass() != null) {
        workflowElem.setAttribute("class", node.getInstanceClass());
      }

      saveConfiguration(node, workflowElem, document);

      // handle preconditions
      if (graph.getPreConditions() != null) {
        Element preConditions = document.createElement("conditions");
        workflowElem.appendChild(preConditions);
        preConditions.setAttribute("type", "pre");
        preConditions.setAttribute("execution", graph.getPreConditions()
            .getModel().getExecutionType());
        preConditions.setAttribute("timeout", String.valueOf(graph.getModel().getTimeout()));
        preConditions.setAttribute("optional", String.valueOf(graph.getModel().isOptional()));
        for (ModelGraph preCondition : graph.getPreConditions().getChildren()) {
          saveGraph(preCondition, preConditions, document);
        }
      }

      // handle subprocessors
      for (ModelGraph subProcessor : graph.getChildren()) {
        saveGraph(subProcessor, workflowElem, document);
      }

      // handle postconditions
      if (graph.getPostConditions() != null) {
        Element postConditions = document.createElement("conditions");
        workflowElem.appendChild(postConditions);
        postConditions.setAttribute("type", "post");
        postConditions.setAttribute("execution", graph.getPostConditions()
            .getModel().getExecutionType());
        postConditions.setAttribute("timeout", String.valueOf(graph.getModel().getTimeout()));
        postConditions.setAttribute("optional", String.valueOf(graph.getModel().isOptional()));
        for (ModelGraph postCondition : graph.getPostConditions().getChildren()) {
          saveGraph(postCondition, postConditions, document);
        }
      }
    }
    if (!node.getExcusedSubProcessorIds().isEmpty()) {
      workflowElem.setAttribute("excused",
          StringUtils.join(node.getExcusedSubProcessorIds(), ","));
    }
    if (node.isEntryPoint()) {
      workflowElem.setAttribute("entryPoint", "true");
    }
  }

  private void saveConfiguration(ModelNode node, Element workflowElem,
      Document document) {
    if (!node.getStaticMetadata().getAllKeys().isEmpty()) {
      Element configElem = document.createElement("configuration");
      workflowElem.appendChild(configElem);
      if (!node.getExtendsConfig().isEmpty()) {
        configElem.setAttribute("extends",
            StringUtils.join(node.getExtendsConfig(), ", "));
      }
      String[] properties = node.getStaticMetadata().getAllKeys()
          .toArray(new String[node.getStaticMetadata().getAllKeys().size()]);
      Arrays.sort(properties);
      for (String property : properties) {
        Element propElem = document.createElement("property");
        configElem.appendChild(propElem);
        propElem.setAttribute("name", property);
        propElem.setAttribute("value",
            node.getStaticMetadata().getMetadata(property));
      }
    }
  }

  private Document createDocument() throws ParserConfigurationException {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    return factory.newDocumentBuilder().newDocument();
  }

  private void ensureUniqueIds(Set<ModelGraph> graphs) {
    for (ModelGraph graph : graphs) {
      HashSet<String> names = new HashSet<String>();
      Vector<ModelGraph> stack = new Vector<ModelGraph>();
      stack.add(graph);
      while (!stack.isEmpty()) {
        ModelGraph currentGraph = stack.remove(0);
        String currentId = currentGraph.getId();
        for (int i = 1; names.contains(currentId); i++)
          currentId = currentGraph.getId() + "-" + i;
        names.add(currentId);
        if (!currentId.equals(currentGraph.getId()))
          currentGraph.getModel().setModelId(currentId);
        stack.addAll(currentGraph.getChildren());
      }
    }
  }

  private ModelGraph loadGraph(List<FileBasedElement> rootElements,
      FileBasedElement workflowNode, Metadata staticMetadata,
      HashMap<String, ConfigGroup> globalConfGroups,
      Set<String> supportedProcessorIds) throws Exception {

    String modelIdRef = null;
    String modelId = null;
    String modelName = null;
    String alias = null;
    String executionType = null;
    List<String> excused = new Vector<String>();
    String clazz = null;
    long timeout = -1;
    boolean optional = false;
    boolean entryPoint = false;

    NamedNodeMap attributes = workflowNode.getElement().getAttributes();
    for (int i = 0; attributes != null && i < attributes.getLength(); i++) {
      Node node = workflowNode.getElement().getAttributes().item(i);
      if (node.getNodeName().equals("id")) {
        modelId = node.getNodeValue();
      } else if (node.getNodeName().equals("name")) {
        modelName = node.getNodeValue();
      } else if (node.getNodeName().equals("class")) {
        clazz = node.getNodeValue();
      } else if (node.getNodeName().equals("id-ref")) {
        modelIdRef = node.getNodeValue();
      } else if (node.getNodeName().equals("excused")) {
        excused.addAll(Arrays.asList(node.getNodeValue().split(",")));
      } else if (node.getNodeName().equals("entryPoint")) {
        entryPoint = Boolean.parseBoolean(node.getNodeValue());
      } else if (node.getNodeName().equals("alias")) {
        alias = node.getNodeValue();
      } else if (node.getNodeName().equals("execution")) {
        executionType = node.getNodeValue();
      } else if (node.getNodeName().equals("timeout")) {
        timeout = node.getNodeValue() != null
            && !node.getNodeValue().equals("") ? Long.valueOf(node
            .getNodeValue()) : -1;
      } 
      else if(node.getNodeName().equals("optional")){
        optional = Boolean.valueOf(node.getNodeValue());
      }
        else if (node.getNodeName().startsWith("p:")) {
        staticMetadata.replaceMetadata(node.getNodeName().substring(2),
            node.getNodeValue());
      }
    }

    if (modelId == null && modelIdRef == null)
      modelId = UUID.randomUUID().toString();

    ModelGraph graph = null;
    if (modelId != null) {

      if (workflowNode.getElement().getNodeName().equals("workflow")
          || workflowNode.getElement().getNodeName().equals("conditions")
          || workflowNode.getElement().getNodeName().equals("tasks")) {
        if (executionType == null) {
          LOG.log(Level.WARNING, "workflow model '"
              + workflowNode.getElement().getNodeName()
              + "' missing execution type: assuming sequential");
          executionType = "sequential";
        }
      } else {
        executionType = workflowNode.getElement().getNodeName();
      }

      if (!supportedProcessorIds.contains(executionType))
        LOG.log(Level.WARNING, "Unsupported execution type id '"
            + executionType + "'");

      ModelNode modelNode = new ModelNode(workflowNode.getFile());
      modelNode.setModelId(modelId);
      modelNode.setModelName(modelName);
      modelNode.setExecutionType(executionType);
      modelNode.setStaticMetadata(staticMetadata);
      modelNode.setExcusedSubProcessorIds(excused);
      modelNode.setInstanceClass(clazz);
      modelNode.setEntryPoint(entryPoint);
      modelNode.setTimeout(timeout);
      modelNode.setOptional(optional);

      loadConfiguration(rootElements, workflowNode, modelNode, globalConfGroups);

      graph = new ModelGraph(modelNode);

      boolean loadedPreConditions = false;
      NodeList children = workflowNode.getElement().getChildNodes();
      for (int i = 0; i < children.getLength(); i++) {
        Node curChild = children.item(i);
        if (curChild.getNodeType() == Node.ELEMENT_NODE) {
          if (curChild.getNodeName().equals("conditions")) {
            boolean isPreCondition = !loadedPreConditions;
            String type = ((Element) curChild).getAttribute("type");
            if (type.length() > 0)
              isPreCondition = type.toLowerCase().equals("pre");
            if (isPreCondition)
              graph.setPreConditions(this.loadGraph(rootElements,
                  new FileBasedElement(workflowNode.getFile(),
                      (Element) curChild), new Metadata(staticMetadata),
                  globalConfGroups, supportedProcessorIds));
            else
              graph.setPostConditions(this.loadGraph(rootElements,
                  new FileBasedElement(workflowNode.getFile(),
                      (Element) curChild), new Metadata(staticMetadata),
                  globalConfGroups, supportedProcessorIds));
            loadedPreConditions = true;
          } else if (!curChild.getNodeName().equals("configuration")
              && !curChild.getNodeName().equals("requiredMetFields")) {
            graph.addChild(this.loadGraph(rootElements, new FileBasedElement(
                workflowNode.getFile(), (Element) curChild), new Metadata(
                staticMetadata), globalConfGroups, supportedProcessorIds));

          }
        }
      }

    } else if (modelIdRef != null) {
      graph = this.findGraph(rootElements, modelIdRef, new Metadata(
          staticMetadata), globalConfGroups, supportedProcessorIds);
      if (graph == null)
        throw new Exception("Workflow '" + modelIdRef
            + "' has not been defined in this context");
      graph.setIsRef(true);
      graph.getModel().setStaticMetadata(new Metadata());
      loadConfiguration(rootElements, workflowNode, graph.getModel(),
          globalConfGroups);
      graph.getModel().setAlias(alias);
    }

    if (entryPoint && graph.getParent() != null) {
      this.graphs.add(graph);
    }

    return graph;
  }

  protected ModelGraph findGraph(List<FileBasedElement> rootElements,
      String modelIdRef, Metadata staticMetadata,
      HashMap<String, ConfigGroup> globalConfGroups,
      Set<String> supportedProcessorIds) throws Exception {
    XPath xpath = XPathFactory.newInstance().newXPath();
    XPathExpression expr = xpath.compile("//*[@id = '" + modelIdRef + "']");
    for (FileBasedElement rootElement : rootElements) {
      Node node = (Node) expr.evaluate(rootElement.getElement(),
          XPathConstants.NODE);
      if (node != null) {
        return this.loadGraph(rootElements,
            new FileBasedElement(rootElement.getFile(), (Element) node),
            staticMetadata, globalConfGroups, supportedProcessorIds);
      }
    }
    return null;
  }

  private void loadConfiguration(List<FileBasedElement> rootElements,
      FileBasedElement workflowNode, ModelNode modelNode,
      HashMap<String, ConfigGroup> globalConfGroups) throws Exception {
    NodeList children = workflowNode.getElement().getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
      Node curChild = children.item(i);
      if (curChild.getNodeName().equals("configuration")) {
        Metadata curMetadata = new Metadata();
        if (modelNode != null
            && !((Element) curChild).getAttribute("extends").equals(""))
          modelNode.setExtendsConfig(Arrays.asList(((Element) curChild)
              .getAttribute("extends").split(",")));
        curMetadata.replaceMetadata(this.loadConfiguration(rootElements,
            curChild, globalConfGroups));
        if (!((Element) curChild).getAttribute("name").equals("")) {
          ConfigGroup configGroup = new ConfigGroup(
              ((Element) curChild).getAttribute("name"), curMetadata);
          if (modelNode != null) {
            List<String> extendsConfig = new Vector<String>(
                modelNode.getExtendsConfig());
            configGroup.addAllExtends(extendsConfig);
            extendsConfig.add(configGroup.getName());
            modelNode.setExtendsConfig(extendsConfig);
          }
          globalConfGroups.put(((Element) curChild).getAttribute("name"),
              configGroup);
        } else if (modelNode != null) {
          modelNode.setStaticMetadata(curMetadata);
        }
      }
    }
  }

  private Metadata loadConfiguration(List<FileBasedElement> rootElements,
      Node configNode, HashMap<String, ConfigGroup> globalConfGroups)
      throws Exception {
    Metadata curMetadata = new Metadata();
    NodeList curGrandChildren = configNode.getChildNodes();
    for (int k = 0; k < curGrandChildren.getLength(); k++) {
      if (curGrandChildren.item(k).getNodeName().equals("property")) {
        Element property = (Element) curGrandChildren.item(k);
        String delim = property.getAttribute("delim");
        String envReplace = property.getAttribute("envReplace");
        String name = property.getAttribute("name");
        String value = property.getAttribute("value");
        if (Boolean.parseBoolean(envReplace))
          curMetadata.replaceMetadata(name + "/envReplace", "true");
        List<String> values = new Vector<String>();
        if (delim.length() > 0)
          values.addAll(Arrays.asList(value.split("\\" + delim)));
        else
          values.add(value);
        curMetadata.replaceMetadata(name, values);
      }
    }
    return curMetadata;
  }

  private class FileBasedElement {

    private File file;
    private Element element;

    public FileBasedElement(File file, Element element) {
      this.file = file;
      this.element = element;
    }

    public File getFile() {
      return this.file;
    }

    public Element getElement() {
      return this.element;
    }

  }

  public class ConfigGroup {

    private String name;
    private Metadata metadata;
    private List<String> extendsConfig;

    public ConfigGroup(String name, Metadata metadata) {
      this.name = name;
      this.metadata = metadata;
      this.extendsConfig = new Vector<String>();
    }

    public String getName() {
      return this.name;
    }

    public Metadata getMetadata() {
      return this.metadata;
    }

    public void addExtends(String child) {
      this.extendsConfig.add(child);
    }

    public void addAllExtends(List<String> children) {
      this.extendsConfig.addAll(children);
    }

    public void removeExtends(String child) {
      this.extendsConfig.remove(child);
    }

    public List<String> getExtends() {
      return this.extendsConfig;
    }

    public int hashCode() {
      return this.name.hashCode();
    }

    public boolean equals(Object obj) {
      if (obj instanceof ConfigGroup) {
        ConfigGroup comp = (ConfigGroup) obj;
        return comp.name.equals(this.name);
      } else
        return false;
    }

    public String toString() {
      return this.name;
    }

  }

}
