var angular = require('angular');
require('../modules');
require('kinetic');
require('../services/Timer');
var module = angular.module('commons.directives.workflowstatus');

/**
 * <div workflow-status flow-type="aaa" record-id="xxx"></div> ->A
 *<workflow-status flow-type="aaa" record-id="xxx"></workflow-status> ->E
 */
module.directive('workflowStatus', function(WorkFlowStatusService, WorkFlowStatus,
  WorkflowNodeImages, $q, Timer) {
  return {
    restrict: 'AE',
    templateUrl: 'views/commons/directives/workflowstatus.tpl.html',
    replace: true,
    scope: {
      flowType: '@flowType',
      recordId: '@recordId',
      offsetPositionConfig: '=offsetPositionConfig'
    },
    link: function(scope, element) {
      var isDestroied = false,
          drawTimer;

      scope.init = function() {
        scope.loadingState = 1;
        scope.dataPromise = $q.all([WorkFlowStatusService.queryFlowStatus(scope.flowType, scope.recordId),
          WorkflowNodeImages.get()]);
        scope.dataPromise
        .then(function(values) {
          var data = values[0],
            images = values[1];

            if (isDestroied) {
              return;
            }

            if(scope.offsetPositionConfig) {
              for (var i = 0; i < data.nodes.length; i ++) {
                data.nodes[i].x -= scope.offsetPositionConfig.left;
                data.nodes[i].y -= scope.offsetPositionConfig.top;
              }
            }

            scope.$broadcast('scroll.resize');
            return drawWorkflowStatus(data, images);
        }).then(function() {
          scope.loadingState = 2;
        }, function() {
          scope.loadingState = 3;
        });
      }

      scope.init();

      function drawWorkflowStatus(data, images) {
        drawTimer = Timer.delay(function() {
            var container = element[0].querySelector('.x-sino-wworkflow-container');
            if (container) {
              var workFlowStatus = new WorkFlowStatus({container: container});
              workFlowStatus.setWorkflowData(data);
              return workFlowStatus.draw(images);
            }
        }, 32);
      }

      scope.$on('$destroy', function() {
        isDestroied = true;
        Timer.clear(drawTimer);
      });
    }
  };
});

module.factory('WorkflowNodeImages', function($q) {
  var config = {
    WEIBAN: 'images/flow/weiban.png',
    QIDONG: 'images/flow/qidong.png',
    YIBAN: 'images/flow/yiban.png',
    BANLIZHONG: 'images/flow/banlizhong.png',
    JIESHU: 'images/flow/jieshu.png'
  };

  function getWorkflowNodeImages() {
    var images = {};
    var promises = _.map(config, function(imageUrl, key) {
      return loadImage(imageUrl).then(function(image) {
        images[key] = image;
      });
    });

    return $q.all(promises)
    .then(function() {
      return images;
    });
  }

  /**
   * 加载图片
   * @param {String} url 图片源地址
   *
   * @return {Promise} 返回promise，包含表示图片的image（DOM）对象。
   */
  function loadImage(url) {
    var image = new Image(),
      defer = $q.defer();
    image.onload = function() {
      defer.resolve(image);
    };
    image.onerror = function() {
      defer.reject();
    };
    image.src = url;
    return defer.promise;
  }

  return {
    get: getWorkflowNodeImages
  };
});

module.factory('WorkFlowStatusService', function($http) {
  return {
    queryFlowStatus: function(flowType, recordId) {
      return $http.get('/workflow/flowStatus?flowType=' + flowType + '&recordId=' + recordId).then(function(response) {
        return response.data;
      });
    }
  };
});

module.factory('WorkFlowStatus', function($toast, CommonService) {
  function WorkFlowStatus(config) {
    this.config = config;
    this.workflowData = {};
    this.nodes = {};
    this.texts = {};
    this.rects = [];
    this.lines = [];
    this.stage = {};
    this.nodeLayer = {};
    this.clicked = false;
  }

  WorkFlowStatus.prototype.setWorkflowData = function(data) {
    this.workflowData = data;
  };

  WorkFlowStatus.prototype.drawNode = function(nodeIndex, imageObj) {
      var node = this.workflowData.nodes[nodeIndex];
      var shape = new Kinetic.Image({
        x: node.x,
        y: node.y,
        id: node.id,
        offsetX: 25,
        offsetY: 25,
        image: imageObj[node.status]
      });

      this.nodes[node.id] = shape;
  };

  WorkFlowStatus.prototype.drawText = function(nodeIndex) {
    var node = this.workflowData.nodes[nodeIndex];
    var shape = this.nodes[node.id];
    var text = new Kinetic.Text({
      fill: 'green',
      text: node.name
    });
    this.addEventListener(node, shape);
    text.x(shape.x() - (text.getWidth() / 2));
    text.y(shape.y() + (text.getHeight() / 2) + 22);
    var rect = new Kinetic.Rect({
          width: text.getWidth() + 10,
          height: text.getHeight() + 8,
          fill: '#c8e0ff',
          strokeWidth: 0
        });

    rect.x(shape.x() - (text.getWidth() / 2) - 5);
    rect.y(shape.y() + (text.getHeight() / 2) + 18);
    this.texts[node.id] = text;
    this.rects[node.id] = rect;
  };

  WorkFlowStatus.prototype.addEventListener = function(node, shape) {
    var self = this;
    function alertMessage() {
      if (node.message && !self.clicked) {
        self.clicked = true;
        CommonService.showAlert(node.message, '流程记录').then(function() {
          self.clicked = false;
        });
      }
    }
    shape.on('tap', alertMessage);
  }

  WorkFlowStatus.prototype.drawLine = function(lineIndex) {
    var line = this.workflowData.lines[lineIndex];
    if (line.start !== line.end) {
      var startNode = this.nodes[line.start];
      var endNode = this.nodes[line.end];
      var startX = startNode.x(),
        startY = startNode.y();
      var endX = endNode.x(),
        endY = endNode.y();
      var bezierLine = new Kinetic.Line({
        dashArray: [10, 10, 0, 10],
        strokeWidth: 3,
        stroke: 'black',
        lineCap: 'round',
        opacity: 0.5
      });
      bezierLine.setPoints([startX, startY, endX, endY]);
      this.lines.push(bezierLine);
    }
  };

  WorkFlowStatus.prototype.setNodeLayer = function() {
    this.nodeLayer.clear();
    for (var j in this.lines) {
      this.nodeLayer.add(this.lines[j]);
    }
    for (var key in this.nodes) {
      this.nodeLayer.add(this.nodes[key]);
      this.nodeLayer.add(this.rects[key]);
      this.nodeLayer.add(this.texts[key]);
    }
  };

  WorkFlowStatus.prototype.draw = function(imageObj) {
    var maxWidth = 0;
    var maxHeight = 0;
    for (var i in this.workflowData.nodes) {
      var n = this.workflowData.nodes[i];
      maxWidth = Math.max(maxWidth, n.x);
      maxHeight = Math.max(maxHeight, n.y);
    }
    maxWidth = maxWidth + 40;
    maxHeight = maxHeight + 40;
    this.config.width = this.config.width || maxWidth;
    this.config.height = this.config.height || maxHeight;
    this.stage = new Kinetic.Stage({
      container: this.config.container,
      width: this.config.width,
      height: this.config.height+15
    });
    for (var nodeIndex in this.workflowData.nodes) {
      this.drawNode(nodeIndex, imageObj);
    }
    for (var lineIndex in this.workflowData.lines) {
      this.drawLine(lineIndex);
    }
    for (var textIndex in this.workflowData.nodes) {
      this.drawText(textIndex, imageObj);
    }
    this.nodeLayer = new Kinetic.Layer();
    this.stage.add(this.nodeLayer);
    this.setNodeLayer();
    this.nodeLayer.draw();
  };
  return WorkFlowStatus;
});
