var angular = require('angular');
require('../modules');
require('../../tree/app');
require('../services/userList');
require('ngIonic');
var module = angular.module('linker.directives');
/**
 * sino-user-select指令用来让用户可以选择人员。
 *
 * 示例：
 *
 * ```
 * <sino-user-select
 * ng-model="evection.togetherNameduty"
 * modal-title="选择同行人"
 * user-name="evection.name"
 * multiple
 * bind-to-name
 * user-name-editable
 * ng-readonly="readonly || !evectionAuth.canEditOther()">
 * </sino-user-select>
 * ```
 *
 * 属性：
 *
 * * ***modal-title***: 人员选择框头部的标题
 * * ***ng-model***: 指定与人员的userId关联的表达式,若是没有userId的则虚构一个ID出来
 * * ***user-name***: 指定与人员的userName,
 * * ***filter-fn***: 指定过滤部门树的过滤器函数。不指定filterFn，则显示整棵部门树。组件内部会调用此函数用来判断哪些部门可以选择，函数可以接受两个参数，即dept代表过滤的部门，superDepts代表所有的父级部门。
 * * ***ng-readonly***: 指定该表单控件是否为只读的。在只读状态下，不可修改选中的人员。
 * * ***multiple***: 指定该表单选择控件是否为多选。如果是多选，则可以选择多个人员。默认为单选。
 * * ***bind-to-name***：选择数据双向绑定的是userID还是username
 * * ***user-name-editable***: 用户名是否可以编辑
 */
module.directive('sinoUserSelect', function($ionicModal, $parse, linkerConfig, userList, $timeout) {

  function userSelectLink(scope, element, attrs, ngModelCtrl) {
    var options = getOptions(attrs);
    var modalOpening = false;
    scope.userNameEditable = options.userNameEditable;
    scope.user = {};

    scope.$watch('userName', function(value) {
      scope.user.userName = value;
    });

    if (!options.boundUserName) {
      scope.$watch(function() {
        return ngModelCtrl.$modelValue;
      }, function(ids) {
        if (ids) {
          userList.get(ids.split(',')).then(function(users) {
            var userNames = [];
            for (var i = 0, len = users.length; i < len; i++) {
              userNames.push(users[i].userName);
            }
            scope.user.userName = userNames.join(',');
          });
        }
      });
    }


    function createOpenUserTreeConfig() {
      var filterFn = attrs.filterFn? function(user, depts, superDepts) {
          return scope.filterFn({
            user: user,
            depts: depts,
            superDepts: superDepts
          });
        } : function() {
          return true;
        };
      var modelValue = ngModelCtrl.$modelValue;
      var userIds = [];
      if (!_.isEmpty(modelValue) && !_.isEmpty(modelValue.replace(/\s+/g, ""))) {
        userIds = modelValue.replace(/\s+/g, "").split(',');
      }

      var config = {
        modalTitle: attrs.modalTitle,
        topDeptId: options.topDeptId,
        type: 'user',
        moreSelect: options.multiple,
        selectType: {
          'user': true,
          'dept': false
        },'default': {
          'userIds':userIds
        },
        filterFn: filterFn
      };
      return config;
    }

    function createModalScope() {
      var modalScope = scope.$new();
      modalScope.treeConfig = createOpenUserTreeConfig();
      modalScope.close = function() {
        if (modalScope.modal) {
          modalScope.modal.hide();
          modalScope.modal.remove();
        }
        modalOpening = false;
      };

      modalScope.$on('$destroy', function() {
        modalScope.close();
      });

      modalScope.$on('selectNode', function(event, users) {
        var ids = [],
          names = [];

        for (var userId in users) {
          if (users.hasOwnProperty(userId)) {
            ids.push(userId);
            names.push(users[userId].userName);
          }
        }

        ngModelCtrl.$setViewValue(ids.join(','));
        scope.userName = names.join(',');
        scope.userId = ids.join(',');
        event.stopPropagation();
      });

      return modalScope;
    }

    scope.openSelectUserModal = function($event) {
      if (attrs.readonly || modalOpening) {
        return;
      }
      modalOpening = true;
      var modalScope = createModalScope();
      $ionicModal.fromTemplateUrl('views/tree/modal/treeModule.tpl.html', {
        scope: modalScope,
        animation: 'slide-in-up',
        hardwareBackButtonClose: true
      }).then(function(modal) {
        modalScope.modal = modal;
        modal.show();
      });
    };
  }

  function userSelectEditableLink(scope, element, attrs, ngModelCtrl) {
    var options = getOptions(attrs);
    var modalOpening = false;
    scope.userNameEditable = options.userNameEditable;
    scope.user = {};

    scope.$watch(function() {
      return ngModelCtrl.$modelValue;
    }, function(value) {
      scope.user.userName = value;
    });

    scope.$watch('user.userName', function(value) {
      ngModelCtrl.$setViewValue(value);
    });

    var userIds = attrs.hasOwnProperty('userIds') && !!attrs.userIds ? attrs.userIds.split(',') : [];

    function createOpenUserTreeConfig() {
      var filterFn = attrs.filterFn? function(user, depts, superDepts) {
          return scope.filterFn({
            user: user,
            depts: depts,
            superDepts: superDepts
          });
        } : function() {
          return true;
        };

      var config = {
        modalTitle: attrs.modalTitle,
        topDeptId: options.topDeptId,
        type: 'user',
        moreSelect: options.multiple,
        selectType: {
          'user': true,
          'dept': false
        },'default': {
          'userIds': userIds
        },
        filterFn: filterFn
      };
      return config;
    }

    function createModalScope() {
      var modalScope = scope.$new();
      modalScope.treeConfig = createOpenUserTreeConfig();
      modalScope.close = function() {
        if (modalScope.modal) {
          modalScope.modal.hide();
          modalScope.modal.remove();
        }
        modalOpening = false;
      };

      modalScope.$on('$destroy', function() {
        modalScope.close();
      });

      modalScope.$on('selectNode', function(event, users) {
        var ids = [],
          names = [];

        for (var userId in users) {
          if (users.hasOwnProperty(userId)) {
            ids.push(userId);
            names.push(users[userId].userName);
          }
        }
        ngModelCtrl.$setViewValue(names.join(','));
        scope.user.userName = scope.userName = names.join(',');
        scope.userId = ids.join(',');
        event.stopPropagation();
      });

      return modalScope;
    }

    function hint(x) {
      var containerRect = element[0].getBoundingClientRect();
      return containerRect.left + containerRect.width - x < 40;
    }

    scope.openSelectUserModal = function($event) {
      var target = $event.target;

      if (attrs.readonly || modalOpening) {
        return;
      }

      if (!hint($event.pageX)) {
        return;
      }

      var textarea = target.tagName === 'textarea'? target :
        target.parentNode.querySelector('textarea');
      if ( textarea ) {
        textarea.setAttribute('readonly', 'readonly');
        $timeout(function() {
          textarea.removeAttribute('readonly');
        }, 100);
      }

      modalOpening = true;
      var modalScope = createModalScope();
      $ionicModal.fromTemplateUrl('views/tree/modal/treeModule.tpl.html', {
        scope: modalScope,
        animation: 'slide-in-up',
        hardwareBackButtonClose: true
      }).then(function(modal) {
        modalScope.modal = modal;
        modal.show();
      });
      $event.stopPropagation();
    };
  }

  function getOptions(attrs) {
    return {
      boundUserName: attrs.hasOwnProperty('userName'),
      readonly: attrs.ngReadonly,
      topDeptId: attrs.topDeptId || linkerConfig.topDeptId,
      multiple: isMultiple(attrs),
      bindToName: attrs.hasOwnProperty('bindToName'),
      userNameEditable: attrs.hasOwnProperty('userNameEditable')
    };
  }

  function isMultiple(attrs) {
    var config = attrs.multiple;
    return attrs.hasOwnProperty('multiple') &&
      config !== 'false' && config != '0';
  }

  return {
    restrict: 'E',
    template: '<div class="sino-user-select" ng-click="openSelectUserModal($event)">' +
      '<p class="sino-user-select-content" ng-if="userNameEditable" >' +
        '<span ng-if="attrs.readonly">{{user.userName}}</span>' +
        '<textarea row="3" ng-model="user.userName" ng-focus="openSelectUserModal($event)" ng-readonly="attrs.readonly" ng-if="!attrs.readonly"></textarea>' +
      '</p>' +
      '<p class="sino-user-select-content" ng-if="!userNameEditable">' +
        '<span>{{user.userName}}</span>' +
        '<select ng-focus="openSelectUserModal($event)" style="display:none;"></select>' +
      '</p>' +
      '<i class="icon ion-ios-person-outline"></i>' +
    '</div>',
    require: '?ngModel',
    replace: true,
    scope: {
      userName: '=?',
      filterFn: '&'
    },
    link: function(scope, element, attrs, ngModelCtrl) {
      if (!ngModelCtrl) {
        return;
      }

      scope.attrs = attrs;

      if (isBindToName()) {
        userSelectEditableLink(scope, element, attrs, ngModelCtrl);
      } else {
        userSelectLink(scope, element, attrs, ngModelCtrl);
      }

      function isBindToName() {
        return attrs.hasOwnProperty('bindToName');
      }
    }
  };
});
