/*
*    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.
*/

import Ember from 'ember';
import CommonUtils from "../utils/common-utils";
import {Workflow} from '../domain/workflow';
import {WorkflowXmlMapper} from '../domain/workflow_xml_mapper';
import SchemaVersions from '../domain/schema-versions';
import Constants from '../utils/constants';

var WorkflowImporter= Ember.Object.extend({
  workflowMapper:null,
  x2js : new X2JS(),
  schemaVersions : SchemaVersions.create({}),
  importWorkflow(workflowXml){
    var workflow=Workflow.create({});
    var errors=[];
    workflow.initialize();
    this.workflowMapper=WorkflowXmlMapper.create({schemaVersions:workflow.schemaVersions});
    return this.processWorkflowXml(workflowXml,workflow, errors);
  },
  processWorkflowXml(workflowXml,workflow, errors){
    var xmlDoc=  Ember.$.parseXML( workflowXml );
    if (xmlDoc && xmlDoc.getElementsByTagName('action').length>Constants.flowGraphMaxNodeCount){
      errors.push({message: "Workflow is too large to be imported",dismissable:true});
      return {workflow:null, errors: errors};
    }
    var workflowJson= this.get("x2js").xml_str2json(workflowXml);
    if (!workflowJson || !workflowJson["workflow-app"]){
      errors.push({message: "Could not import invalid workflow",dismissable:true});
      return {workflow:null, errors: errors};
    }
    var workflowAppJson=workflowJson["workflow-app"];
    var workflowVersion=CommonUtils.extractSchemaVersion(workflowAppJson._xmlns);
    var maxWorkflowVersion = Math.max.apply(Math, this.get('schemaVersions').getSupportedVersions('workflow'));
    if (workflowVersion > maxWorkflowVersion) {
      errors.push({message: "Unsupported workflow version - " + workflowVersion});
    } else {
      workflow.schemaVersions.workflowVersion = workflowVersion;
    }
    this.processWorkflowActionVersions(workflowAppJson, workflow, errors);

    if (workflowAppJson.info && workflowAppJson.info.__prefix==="sla") {
      workflow.slaEnabled=true;
      this.workflowMapper.handleSLAImport(workflow,workflowAppJson.info);
    }
    this.workflowMapper.handleCredentialImport(workflow,workflowAppJson.credentials);
    this.workflowMapper.handleParametersImport(workflow,workflowAppJson.parameters);
    var nodeMap=this.setupNodeMap(workflowAppJson,workflow,Ember.$(xmlDoc));
    this.setupTransitions(workflowAppJson,nodeMap);
    workflow.set("startNode",nodeMap.get("start").node);
    this.populateKillNodes(workflow,nodeMap);
    return {workflow: workflow, errors: errors};
  },
  processWorkflowActionVersions(workflowAppJson, workflow, errors) {
    var importedWfActionVersions = Ember.Map.create();
    var actions=workflowAppJson.action ? (workflowAppJson.action.length?workflowAppJson.action:[workflowAppJson.action]):[];
    actions.forEach(function(wfAction) {
      var wfActionType = Object.keys(wfAction)[0];
      var wfActionXmlns = wfAction[wfActionType]._xmlns;
      if (!wfActionXmlns) {
        return;
      }
      var wfActionVersion = CommonUtils.extractSchemaVersion(wfActionXmlns);
      if (importedWfActionVersions.get(wfActionType)) {
        importedWfActionVersions.get(wfActionType).push(wfActionVersion);
      } else {
        importedWfActionVersions.set(wfActionType, [wfActionVersion]);
      }
    });

    importedWfActionVersions._keys.forEach(function(wfActionType){
      if(!CommonUtils.isSupportedAction(wfActionType)){
        return;
      }
      var maxImportedActionVersion = Math.max.apply(null,importedWfActionVersions.get(wfActionType));
      var supportedVersions = this.get('schemaVersions').getSupportedVersions(wfActionType);
      importedWfActionVersions.get(wfActionType).forEach((version)=>{
        if(supportedVersions.indexOf(version) === -1){
          errors.push({message: "Unsupported " + wfActionType + " version - " + maxImportedActionVersion});
        }else{
          workflow.schemaVersions.actionVersions.set(wfActionType, maxImportedActionVersion);
        }
      }, this);
    }, this);
  },
  processActionNode(nodeMap,action){
    var actionMapper=this.get("workflowMapper").getNodeHandler("action");
    var actionNode=actionMapper.handleImportNode(action);
    nodeMap.set(actionNode.getName(),actionNode);
  },
  setupNodeMap(workflowAppJson,workflow,xmlDoc){
    var self=this;
    workflow.set("name",workflowAppJson["_name"]);
    var nodeMap=new Map();
    Object.keys(workflowAppJson).forEach(function (key) {
      var nodeHandler=self.workflowMapper.getNodeHandler(key);
      if (nodeHandler){
        if (Ember.isArray(workflowAppJson[key])){
          workflowAppJson[key].forEach(function(jsonObj){
            var actionDom = xmlDoc.find("action[name='" + jsonObj._name + "']");
            var node = nodeHandler.handleImportNode(key,jsonObj,workflow,actionDom);
            nodeMap.set(jsonObj._name,{json:jsonObj,node:node});
          });
        }else{
          if ('action'===key){//action handler.
          	var actionDom=xmlDoc.find("action[name='"+workflowAppJson[key]._name+ "']");
          }
          var node=nodeHandler.handleImportNode(key,workflowAppJson[key],workflow,actionDom);
          if (!workflowAppJson[key]._name){
            nodeMap.set(key,{json:workflowAppJson[key],node:node});
          }else{
            nodeMap.set(workflowAppJson[key]._name,{json:workflowAppJson[key],node:node});
          }
        }
      }
    });
    return nodeMap;
  },
  setupTransitions(workflowAppJson,nodeMap){
    var self=this;
    nodeMap.forEach(function(entry,key){
      var node=entry.node;
      if (!node){
        console.error("could not process:",key);//TODO error handling...
        return;
      }
      var json=entry.json;
      var nodeHandler=self.workflowMapper.getNodeHandler(node.get("type"));
      if (!nodeHandler){
        console.error("could not process:",node.get("type"));//TODO error handling...
      }
      nodeHandler.handleImportTransitions(node,json,nodeMap);
    });
  },
  getNodeIds(nodeMap){
    var ids=[];
    nodeMap.forEach(function(entry){
      var node=entry.node;
      ids.push(node.id);
    });
    return ids;
  },
  getNodeNames(nodeMap){
    var names=[];
    nodeMap.forEach(function(entry){
      var node=entry.node;
      names.push(node.id);
    });
    return names;
  },
  populateKillNodes(workflow,nodeMap){
    if (this.containsKillNode(nodeMap)){
      workflow.resetKillNodes();
    }
    nodeMap.forEach(function(entry){
      var node=entry.node;
      if (node.isKillNode()){
        workflow.get("killNodes").pushObject(node);
      }
    });
  },
  containsKillNode(nodeMap){
    var containsKillNode=false;
    nodeMap.forEach(function(entry){
      var node=entry.node;
      if (node.isKillNode()){
        containsKillNode=true;
      }
    });
    return containsKillNode;
  }
});
export {WorkflowImporter};
