'use strict';

app.directive('addToList', function (){
  return {
    restrict: 'A',
    scope: {
      fn: '&',
      list: '='
    },
    link: function(scope, element, attrs, ctrl) {
      element.on('click', function(event) {
        scope.$apply(function() {
          scope.list.push(scope.fn());
        });
      });
    }
  };
});
'use strict';
app.directive('autoFocus', function ($timeout) {
  return {
    restrict: 'AC',
    link: function(scope, element) {
      $timeout(function(){
          element[0].focus();
      }, 0);
    }
  };
});
'use strict';

app.directive('autoTabTo', function () {
  return {
    restrict: 'A',
    link: function (scope, el, attrs) {
      el.bind('keyup', function(e) {
        
        if (this.value.length === this.maxLength) {
          var element = document.getElementById(attrs.autoTabTo);
          if (element) { element.focus(); }
        }
      });
    }
  };
});
'use strict';
/**
 * Checklist-model
 * AngularJS directive for list of checkboxes
 */

angular.module('checklist-model', [])
.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
  

  // contains
  function contains(arr, item, compareOn) {
    if (angular.isArray(arr)) {

      for (var i = arr.length; i--;) {
        var boolArray = [];
        for (var j = compareOn.length; j--;) {
          boolArray.push(arr[i][compareOn[j]] === item[compareOn[j]]);
        }

        if (angular.equals(arr[i], item) || boolArray.every(Boolean) ) {
          return true;
        }
      }
    }
    return false;
  }

  // add
  function add(arr, item, compareOn) {
    arr = angular.isArray(arr) ? arr : [];
    if (contains(arr, item, compareOn)) {
      return arr;
    }
    arr.push(item);
    return arr;
  }  

  // remove
  function remove(arr, item, compareOn) {
    if (angular.isArray(arr)) {
      for (var i = arr.length; i--;) {
        var boolArray = [];
        for (var j = compareOn.length; j--;) {
          boolArray.push(arr[i][compareOn[j]] === item[compareOn[j]]);
        }

        if (angular.equals(arr[i], item) || boolArray.every(Boolean) ) {
          arr.splice(i, 1);
          break;
        }
      }
    }
    return arr;
  }

  // http://stackoverflow.com/a/19228302/1458162
  function postLinkFn(scope, elem, attrs) {
    // compile with `ng-model` pointing to `checked`
    $compile(elem)(scope);

    // getter / setter for original model
    var getter = $parse(attrs.checklistModel);
    var setter = getter.assign;

    // evaluates the array passed into the attribute
    var compareOn = scope.$eval(attrs.checklistCompareOn);
    
    // value added to list
    var value = $parse(attrs.checklistValue)(scope.$parent);

    // watch UI checked change
    scope.$watch('checked', function(newValue, oldValue) {
      if (newValue === oldValue) { 
        return;
      } 
      var current = getter(scope.$parent);
      if (newValue === true) {
        setter(scope.$parent, add(current, value, compareOn));
      } else {
        setter(scope.$parent, remove(current, value, compareOn));
      }
    });

    // watch original model change
    scope.$parent.$watchCollection(attrs.checklistModel, function(newArr, oldArr) {
      scope.checked = contains(newArr, value, compareOn);
    });
  }

  return {
    restrict: 'A',
    priority: 1000,
    terminal: true,
    scope: true,
    compile: function(tElement, tAttrs) {
      if (tElement[0].tagName !== 'INPUT' || !tElement.attr('type', 'checkbox')) {
        throw 'checklist-model should be applied to `input[type="checkbox"]`.';
      }

      if (!tAttrs.checklistValue) {
        throw 'You should provide `checklist-value`.';
      }

      // exclude recursion
      tElement.removeAttr('checklist-model');
      
      // local scope var storing individual checkbox model
      tElement.attr('ng-model', 'checked');

      return postLinkFn;
    }
  };
}]);
'use strict';

app.directive('clearArray', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: {
      array: '='
    },
    link: function(scope, element, attrs) {
      
      function clearAll() {
        var arr = scope.array;
        while(arr.length > 0) {
          arr.pop();                     
        }
      }

      element.on('click', function(event) {
        //event.preventDefault();
        scope.$apply(clearAll);
      });
    }
  };
});
'use strict';

app.directive('clickAndDisable', function() {
  return {
    scope: {
      clickAndDisable: '&'
    },
    link: function(scope, elem, attrs) {
      elem.bind('click', function() {
        elem.prop('disabled',true);
        scope.clickAndDisable().finally(function() {
          elem.prop('disabled',false);
        });
      });
    }
  };
});
'use strict'; 

app.directive('confirmDelete', function($window) {

  function link(scope, element, attrs) {
    element.on('click', function(event) {
      event.preventDefault();  
      if ($window.confirm('Are you sure you want to delete ' + scope.item.name + '?')) {
        var idx = scope.list.indexOf(scope.item);
        scope.$apply(function() {     
          scope.list.splice(idx, 1);
        });
      }
    });  
  }

  return {
    restrict: 'A',
    scope: {
      item: '=',
      list: '='
    },
    link: link
  };
});
'use strict';
//source: https://docs.angularjs.org/guide/directive

app.directive('currentTime', ['$interval', 'dateFilter', function($interval, dateFilter) {

  function link(scope, element, attrs) {
    var format,
        timeoutId;

    function updateTime() {
      element.text(dateFilter(new Date(), format));
    }

    scope.$watch(attrs.currentTime, function(value) {
      format = value;
      console.log(value);
      updateTime();
    });

    element.on('$destroy', function() {
      $interval.cancel(timeoutId);
    });

    // start the UI update process; save the timeoutId for canceling
    timeoutId = $interval(function() {
      updateTime(); // update DOM
    }, 1000);
  }

  return {
    link: link
  };
}]);
'use strict';

app.directive('deleteFromList', function() {
  return {
    restrict: 'A',
    scope: {
      item: '=',
      list: '='
    },
    link: function(scope, element, attrs, ctrl) {
      element.on('click', function(event) {
        var idx = scope.list.indexOf(scope.item);
        scope.$apply(function() {
          
          scope.list.splice(idx, 1);
        });
      });
    }
  };
});
'use strict';

app.directive('enterPress', function () {
  return function(scope, element, attrs) {
      element.bind('keydown keypress', function(event) {
          if(event.which === 13) {
              scope.$apply(function(){
                  scope.$eval(attrs.enterPress, {'event': event});
              });

              event.preventDefault();
          }
      });
  };
});

'use strict';

app.directive('forceInteger', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    scope: {
      ngModel: '='
    },
    link: function(scope, element, attrs) {
      scope.$watch(function(){
        return scope.ngModel;
      }, function(){
          scope.ngModel = Number(scope.ngModel);
          console.log(scope.ngModel, typeof scope.ngModel);
      },true);
    }
  };
});



// app.directive('forceInteger', function(){
//   return {
//     restrict: 'A',
//     require: 'ngModel',
//     link: function(scope, element, attr, ngModelCtrl){
//       ngModelCtrl.$parsers.unshift(function(viewValue){
//         console.log(viewValue);
//         return parseInt(viewValue, 10);
//       });
//     }
//   };
// });
'use strict';
app.directive('loadingContainer', function () {
    return {
        restrict: 'A',
        scope: false,
        link: function(scope, element, attrs) {
            var loadingLayer = angular.element('<div class="loading"></div>');
            element.append(loadingLayer);
            element.addClass('loading-container');
            scope.$watch(attrs.loadingContainer, function(value) {
                loadingLayer.toggleClass('ng-hide', !value);
            });
        }
    };
});
'use strict';
app.directive('match', [function () {
    return {
      require: 'ngModel',
      restrict: 'A',
      scope: {
          match: '='
      },
      link: function(scope, elem, attrs, ctrl) {
          scope.$watch(function() {
              var modelValue = ctrl.$modelValue || ctrl.$$invalidModelValue;
              return (ctrl.$pristine && angular.isUndefined(modelValue)) || scope.match === modelValue;
          }, function(currentValue) {
              ctrl.$setValidity('match', currentValue);
          });
      }
    };
}]);

'use strict';

app.directive('optionsDisabled', function($parse) {
  var disableOptions = function(scope, attr, element, data, fnDisableIfTrue) {
    // refresh the disabled options in the select element.
    angular.forEach(element.find("option"), function(value, index){
      var elem = angular.element(value);
      if(elem.val() !== ""){
        var locals = {};
        locals[attr] = data[index];
        elem.attr("disabled", fnDisableIfTrue(scope, locals));
      }
    });
  };
  
  return {
    priority: 0,
    require: 'ngModel',
    link: function(scope, iElement, iAttrs, ctrl) {
      // parse expression and build array of disabled options
      var expElements = iAttrs.optionsDisabled.match(/^\s*(.+)\s+for\s+(.+)\s+in\s+(.+)?\s*/);
      var attrToWatch = expElements[3];
      var fnDisableIfTrue = $parse(expElements[1]);
      scope.$watch(attrToWatch, function(newValue, oldValue) {
          if(newValue) {
            disableOptions(scope, expElements[2], iElement, newValue, fnDisableIfTrue);
          }   
      }, true);
      // handle model updates properly
      scope.$watch(iAttrs.ngModel, function(newValue, oldValue) {
          var disOptions = $parse(attrToWatch)(scope);
          if(newValue) {
            disableOptions(scope, expElements[2], iElement, disOptions, fnDisableIfTrue);
          }
      });
    }
  };
});
'use strict';

app.directive('searchModels', function ($modal, toastr, Database) {
	return {
		restrict: 'A',
		scope: {
			dbType: '=',
			brand: '=',
			query: '=',
			result: '=',
			event: '@' //takes a string for event type, click or keypress (mapped to enter key)
		},
		link: function(scope, element, attrs, ctrl) {
			function updateModel() {
				Database.searchModels(scope.dbType, scope.brand, scope.query)
				.then(function(devices) {
					console.log(devices);
					//scope.device.targetType = null;
					//scope.device.model = null;

					scope.result = devices;

					devices.irSearchResult = false;
					devices.ipSearchResult = false;

					if (!devices.ir.length && !devices.ip.length) {
						$modal({
							title: 'No Models Found',
							content: 'The model you searched for was not found. You may try searching again or choose from the list of popular models.',
							show: true
						});
					}

					if (!devices.ir.length) {
						_.forEach(devices.p_ir, function(device, i) {
							device.index = i;
							scope.result.ir.push(device);  
						});
					} else {
						devices.irSearchResult = true;
					}

					if (!devices.ip.length) {
						_.forEach(devices.p_ip, function(device, i) {
							device.index = i;
							scope.result.ip.push(device);  
						});
					} else {
						devices.ipSearchResult = true;
					}
				})
				.catch(function(error) {
					toastr.error(error, 'Error');
				});     
			}

			if (scope.event === 'click') {    
				element.on('click', function(event) {
					console.log('element clicked');
					scope.$apply(updateModel);
				});
			} else {
				element.bind("keypress", function (event) {
					var key = event.keyCode || event.which;
					if(key === 13) {
						scope.$apply(updateModel);       
					}
				});
			}
			
		}
	};
});
'use strict';

app.directive('submitAndDisable', function() {
  return {
    scope: {
      submitAndDisable: '&'
    },
    link: function(scope, elem, attrs) {
      console.log(elem);
      elem.bind('submit', function() {
        var btn = angular.element('button[type=submit]');
        btn.prop('disabled',true);
        scope.submitAndDisable().finally(function() {
          btn.prop('disabled',false);
        });
      });
    }
  };
});
'use strict';
app.directive('unique', [function () {
    return {
      require: 'ngModel',
      restrict: 'A',
      scope: {
          unique: '='
      },
      link: function(scope, elem, attrs, ctrl) {
          scope.$watch(function() {
              var modelValue = ctrl.$modelValue || ctrl.$$invalidModelValue;
              return (ctrl.$pristine && angular.isUndefined(modelValue)) || scope.unique !== modelValue;
          }, function(currentValue) {
              ctrl.$setValidity('unique', currentValue);
          });
      }
    };
}]);
