/**
 * Created by 二哲 on 15/12/6.
 */
/*
 * 不带参数指令
 * v-tap=handler
 * or
 * 带参数指令
 * v-tap=handler($index,el,$event)
 *
 * !!!新增!!!
 * 把tapObj对象注册在原生event对象上
 * 	event.tapObj拥有6个值
 * 	pageX,pageY,clientX,clientY,distanceX,distanceY
 * 后面2个分别的手指可能移动的位置(以后可用于拓展手势)
 *
 * */
;(function () {
  var vueTap = {};
  var isVue2 = false;

  /**                               公用方法开始                 **/
  function isPc() {
    var uaInfo = navigator.userAgent;
    var agents = ["Android", "iPhone", "Windows Phone", "iPad", "iPod"];
    var flag = true;
    for ( var i = 0; i < agents.length; i++ ) {
      if (uaInfo.indexOf(agents[i]) > 0) {
        flag = false;
        break;
      }
    }
    return flag;
  }

  function isTap(self) {
    if (isVue2 ? self.disabled : self.el.disabled) {
      return false;
    }
    var tapObj = self.tapObj;
    return self.time < 300 && Math.abs(tapObj.distanceX) < 10 && Math.abs(tapObj.distanceY) < 10;
  }

  function touchstart(e, self) {
    var touches = e.touches[0];
    var tapObj = self.tapObj;
    tapObj.pageX = touches.pageX;
    tapObj.pageY = touches.pageY;
    tapObj.clientX = touches.clientX;
    tapObj.clientY = touches.clientY;
    self.time = +new Date();
  }

  function touchend(e, self) {
    var touches = e.changedTouches[0];
    var tapObj = self.tapObj;
    self.time = +new Date() - self.time;
    tapObj.distanceX = tapObj.pageX - touches.pageX;
    tapObj.distanceY = tapObj.pageY - touches.pageY;

    if (!isTap(self)) return;
    self.handler(e);

  }

  /**                               公用方法结束                 * */

  var vue1 = {
    isFn: true,
    acceptStatement: true,
    update: function (fn) {
      var self = this;
      self.tapObj = {};
      if (typeof fn !== 'function' && self.el.tagName.toLocaleLowerCase() !== 'a') {
        return console.error('The param of directive "v-tap" must be a function!');
      }

      self.handler = function (e) { //This directive.handler
        e.tapObj = self.tapObj;
        if (self.el.href && !self.modifiers.prevent) {
          return window.location = self.el.href;
        }

        var tagName = e.target.tagName.toLocaleLowerCase();
        if(tagName === 'input' || tagName === 'textarea') {
          return e.target.focus();
        }

        fn.call(self, e);
      };
      if (isPc()) {
        self.el.addEventListener('click', function (e) {
          if (self.el.href && !self.modifiers.prevent) {
            return window.location = self.el.href;
          }
          self.handler.call(self, e);
        }, false);
      } else {
        self.el.addEventListener('touchstart', function (e) {

          if (self.modifiers.stop)
            e.stopPropagation();
          if (self.modifiers.prevent)
            e.preventDefault();
          touchstart(e, self);
        }, false);
        self.el.addEventListener('touchend', function (e) {
          try {
            Object.defineProperty(e, 'currentTarget', {// 重写currentTarget对象 与jq相同
              value: self.el,
              writable: true,
              enumerable: true,
              configurable: true
            })
          } catch (e) {
            // ios 7下对 e.currentTarget 用defineProperty会报错。
            // 报“TypeError：Attempting to configurable attribute of unconfigurable property”错误
            // 在catch里重写
            console.error(e.message)
            e.currentTarget = self.el
          }
          e.preventDefault();

          return touchend(e, self);
        }, false);
      }
    }
  };

  var vue2 = {
    bind: function (el, binding) {
      el.tapObj = {};
      el.handler = function (e,isPc) { //This directive.handler
        var value = binding.value;

        if (!value && el.href && !binding.modifiers.prevent) {
          return window.location = el.href;
        }

        value.event = e;
        var tagName = value.event.target.tagName.toLocaleLowerCase();
        !isPc ? value.tapObj = el.tapObj : null;

        if(tagName === 'input' || tagName === 'textarea') {
          return value.event.target.focus();
        }

        value.methods.call(this, value);
      };
      if (isPc()) {
        el.addEventListener('click', function (e) {

          if (binding.modifiers.stop)
            e.stopPropagation();
          if (binding.modifiers.prevent)
            e.preventDefault();
          el.handler(e, true)
        }, false);
      } else {
        el.addEventListener('touchstart', function (e) {

          if (binding.modifiers.stop)
            e.stopPropagation();
          if (binding.modifiers.prevent)
            e.preventDefault();
          touchstart(e, el);
        }, false);
        el.addEventListener('touchend', function (e) {
          try {
            Object.defineProperty(e, 'currentTarget', {// 重写currentTarget对象 与jq相同
              value: el,
              writable: true,
              enumerable: true,
              configurable: true
            })
          } catch (e) {
            // ios 7下对 e.currentTarget 用defineProperty会报错。
            // 报“TypeError：Attempting to configurable attribute of unconfigurable property”错误
            // 在catch里重写
            console.error(e.message)
            e.currentTarget = el
          }
          e.preventDefault();

          return touchend(e, el);
        }, false);
      }
    },
    componentUpdated : function(el,binding) {
      el.tapObj = {};
      el.handler = function (e,isPc) { //This directive.handler
        var value = binding.value;
        if (!value && el.href && !binding.modifiers.prevent) {
          return window.location = el.href;
        }
        value.event = e;
        !isPc ? value.tapObj = el.tapObj : null;
        value.methods.call(this, value);
      };
    },
    unbind: function (el) {
      // 卸载，别说了都是泪
      el.handler = function () {};
    }
  };

  vueTap.install = function (Vue) {
    if (Vue.version.substr(0, 1) > 1) {
      isVue2 = true;
    }

    Vue.directive('tap', isVue2 ? vue2 : vue1);
  };
  vueTap.version = '3.0.3';

  if (typeof exports == "object") {
    module.exports = vueTap;
  } else if (typeof define == "function" && define.amd) {
    define([], function () {
      return vueTap
    })
  } else if (window.Vue) {
    window.vueTap = vueTap;
    Vue.use(vueTap);
  }

})();

