'use strict';
var angular = require('angular');
require('../modules');
require('./GestureScreenLayout');
var module = angular.module('gesturepassword.services');

module.factory('GestureScreenContext', function(GestureScreenLayout, $rootScope) {

  function GestureScreenContext(width, height, validator, setpassword, ctx) {
    this.setpassword = setpassword;
    this.ctx = ctx;
    this.firstpassword = '';
    this.width = width;
    this.height = height;
    this.validator = validator || function() {return true;};
    this.layout = new GestureScreenLayout(width, height).calc();
    this.contentWidth = this.layout.content.width;
    this.contentHeight = this.layout.content.height;
    this.pointers = GestureScreenContext.generatePoints(this.layout.content);
    this.selectors = [];
    this.sceneState = GestureScreenContext.STATE_PRIMITIVE;
    this.addedSelectors = [];
  }

  GestureScreenContext.POINTER_NUMBER = 9;

  GestureScreenContext.STATE_PRIMITIVE = 0;
  GestureScreenContext.STATE_MOVING = 1;
  GestureScreenContext.STATE_OK = 2;
  GestureScreenContext.STATE_NO = 3;

  GestureScreenContext.POINTER_STATE_PRIMITIVE = 0;
  GestureScreenContext.POINTER_STATE_SELECTED = 1;
  GestureScreenContext.POINTER_STATE_OK = 2;
  GestureScreenContext.POINTER_STATE_NO = 3;

  /**
   * 产生九个点。
   * 
   * @param  {ContentLayout} 内容区域布局对象
   * @return {Array}         返回九个点。
   */
  GestureScreenContext.generatePoints = function(contentLayout) {
    var startX = contentLayout.gap,
      startY = contentLayout.topWhite,
      radius = contentLayout.radius,
      gap = contentLayout.gap,
      pointers = [];

    for (var i = 0; i < GestureScreenContext.POINTER_NUMBER; i++) {
      var relativeX = i % 3,
        relativeY = Math.floor(i / 3);
      pointers.push({
        y: (startY + (2 * relativeY + 1) * radius + relativeY * gap + 0.5) | 0,
        x: (startX + (2 * relativeX + 1) * radius + relativeX * gap + 0.5) | 0,
        radius: radius,
        state: GestureScreenContext.STATE_PRIMITIVE
      });
    }
    return pointers;
  };

  GestureScreenContext.pointerInCircle = function(circle, pointer) {
    return Math.pow((circle.x - pointer.x), 2) +
      Math.pow(circle.y - pointer.y, 2) <= Math.pow(circle.radius, 2);
  };

  /**
   * 矫正两点之间的两线，若之间还有点，应该连上
   * @param  {[Array]} selectors 已选择的点
   * @param  {[int]} selector  当前选择的点
   * @return {[int]} 返回中间点索引
   */
  GestureScreenContext.makeLineCorrect = function(selectors, selector) {
    if (selectors.length <= 0) { return; }
    var array = [
      '0,8,4','8,0,4','2,6,4','6,2,4','0,6,3','6,0,3','1,7,4','7,1,4',
      '2,8,5','8,2,5','0,2,1','2,0,1','3,5,4','5,3,4','6,8,7','8,6,7'
      ],
      linkSelector = selectors[selectors.length - 1] + ',' + selector,
      i;
    for (i = 0; i < array.length; i ++) {
      var currentGroup = array[i];
      if (currentGroup.substring(0, 3) === linkSelector) {
        return parseInt(currentGroup.charAt(currentGroup.length - 1));
      }
    }
  };

  GestureScreenContext.prototype = {
    /**
     * 开始移动
     *
     * @param  {Number} x
     * @param  {Number} y
     */
    startMove: function() {
      if (this.sceneState === GestureScreenContext.STATE_PRIMITIVE) {
        this.setState(GestureScreenContext.STATE_MOVING);
      } else if (this.sceneState === GestureScreenContext.STATE_NO) {
        this.setState(GestureScreenContext.STATE_PRIMITIVE);
        this.setState(GestureScreenContext.STATE_MOVING);
      }
    },

    /**
     * 移动中
     * 
     * @param  {Number} x
     * @param  {Number} y
     */
    move: function(x, y) {
      if (this.sceneState === GestureScreenContext.STATE_MOVING) {
        this.movingPointer = {
          x: (x - this.layout.content.startX + 0.5) | 0,
          y: (y - this.layout.content.startY + 0.5) | 0
        };
        this.checkSelectors();
      }
    },

    /**
     * 移动结束
     * 
     * @return
     */
    endMove: function() {
      var result = this.validate(),
        toState = result? GestureScreenContext.STATE_OK : GestureScreenContext.STATE_NO;
      delete this.movingPointer;
      this.setState(toState);
      return result;
    },

    setState: function(state) {
      var stateChanged = this.sceneState !== state;
      this.sceneState = state;
      switch(state) {
        case GestureScreenContext.STATE_PRIMITIVE:
          this.reset();
          break;
        case GestureScreenContext.STATE_MOVING:
          break;
        case GestureScreenContext.STATE_OK:
          this.changeSelectorPointersState(GestureScreenContext.POINTER_STATE_OK);
          break;
        case GestureScreenContext.STATE_NO:
          this.changeSelectorPointersState(GestureScreenContext.POINTER_STATE_NO);
          break;
      }
      if (stateChanged) {
        $rootScope.$broadcast('gesturepassword.statechange', this, state);
        $rootScope.$emit('gesturepassword.statechange', this, state);
      }
    },

    changeSelectorPointersState: function(state) {
      var i, index, pointer;
      for (i = this.selectors.length; i--;) {
        index = this.selectors[i];
        pointer = this.pointers[index];
        pointer.state = state;
      }
    },

    reset: function() {
      this.selectors = [];
      _.forEach(this.pointers, function(pointer) {
        pointer.state = GestureScreenContext.POINTER_STATE_PRIMITIVE;
      });
      delete this.movingPointer;
    },

    /**
     * 
     */
    checkSelectors: function () {
      var i, pointer, pointerMiddle;
      for (i = this.pointers.length; i--;) {
        pointer = this.pointers[i];
        if (GestureScreenContext.pointerInCircle(pointer, this.movingPointer)) {
          if (pointer.state !== GestureScreenContext.POINTER_STATE_SELECTED) {
            pointer.state = GestureScreenContext.POINTER_STATE_SELECTED;
            var j = GestureScreenContext.makeLineCorrect(this.selectors, i);
            if(j >= 0) {
              pointerMiddle = this.pointers[j];
              if (pointerMiddle.state !== GestureScreenContext.POINTER_STATE_SELECTED) {
                pointerMiddle.state = GestureScreenContext.POINTER_STATE_SELECTED;
                this.selectors.push(j);
                this.addedSelectors.push(j);
              }
            }
            this.selectors.push(i);
            this.addedSelectors.push(i);
          }
          return;
        }
      }
    },

    /**
     * 移动结束后验证正确与否
     */
    validate: function() {
      return this.validator(this.selectors);
    },

    /**
     * 传入第一次设置的密码，是缩略图在第一次成功设置密码时，把密码传入
     */
    setFirspassword: function(firstpassword) {
      this.firstpassword = firstpassword;
    },

    destroy: function() {
      delete this.layout;
      delete this.ctx;
      delete this.validator;
      delete this.pointers;
    }

  };

  return GestureScreenContext;
});