/**
 * Checklist-model
 * AngularJS directive for list of checkboxes
 */

angular.module('checklist-model', [])
.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
  // contains
  function contains(arr, item) {
    if (angular.isArray(arr)) {
      for (var i = 0; i < arr.length; i++) {
        if (angular.equals(arr[i], item)) {
          return true;
        }
      }
    }
    return false;
  }

  // add
  function add(arr, item) {
    arr = angular.isArray(arr) ? arr : [];
    for (var i = 0; i < arr.length; i++) {
      if (angular.equals(arr[i], item)) {
        return arr;
      }
    }    
    arr.push(item);
    return arr;
  }  

  // remove
  function remove(arr, item) {
    if (angular.isArray(arr)) {
      for (var i = 0; i < arr.length; i++) {
        if (angular.equals(arr[i], item)) {
          arr.splice(i, 1);
          return;
        }
      }
    }
  }

  // http://stackoverflow.com/a/19228302/1458162
  function postLinkFn(scope, elem, attrs) {
    // compile with `ng-model` pointing to `checked`
    $compile(elem)(scope);
    // link to original model. Initially assigned in $watch
    var model;
    // need setter for case when original model not array
    var setter = $parse(attrs.checklistModel).assign;
    // 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;
      } if (newValue === true) {
        // see https://github.com/vitalets/checklist-model/issues/11
        if (!angular.isArray(model)) {
          setter(scope.$parent, add([], value));
          // `model` will be updated in $watch
        } else {
          add(model, value);
        }
      } else if (newValue === false) {
        remove(model, value);
      }
    });

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

  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 var storing individual checkbox model
      // scope.checked - will be set in $watch
      tElement.attr('ng-model', 'checked');

      return postLinkFn;
    }
  };
}]);

@@ -864,38 +864,37 @@
 , 1);%0A          
+b
 re
-turn
+ak
 ;%0A        %7D%0A    
@@ -903,16 +903,32 @@
 %7D%0A    %7D%0A
+    return arr;%0A
   %7D%0A%0A  /
@@ -1101,94 +1101,24 @@
 e);%0A
+%0A
     // 
-link to original model. Initially assigned in $watch%0A    var model;%0A    // need
+getter /
  set
@@ -1129,18 +1129,8 @@
 for 
-case when 
 orig
@@ -1143,18 +1143,8 @@
 odel
- not array
 %0A   
@@ -1148,17 +1148,17 @@
     var 
-s
+g
 etter = 
@@ -1185,16 +1185,41 @@
 stModel)
+;%0A    var setter = getter
 .assign;
@@ -1219,16 +1219,17 @@
 assign;%0A
+%0A
     // v
@@ -1463,143 +1463,83 @@
   %7D 
-if (newValue === true) %7B%0A        // see https://github.com/vitalets/checklist-model/issues/11%0A 
+%0A      var current = getter(scope.$parent);%0A
       
- 
 if (
-!angular.isArray(model)
+newValue === true
 ) %7B%0A
-  
     
@@ -1568,18 +1568,23 @@
 nt, add(
-%5B%5D
+current
 , value)
@@ -1596,159 +1596,54 @@
     
-    // %60model%60 will be updated in $watch%0A        %7D else %7B%0A          add(model, value);%0A        %7D%0A      %7D else if (newValue === false) %7B%0A       
+%7D else %7B%0A        setter(scope.$parent,
  remove(
 mode
@@ -1642,21 +1642,23 @@
 ove(
-model
+current
 , value)
 ;%0A  
@@ -1649,24 +1649,25 @@
 rent, value)
+)
 ;%0A      %7D%0A  
@@ -1686,16 +1686,25 @@
 / watch 
+original 
 model ch
@@ -1786,69 +1786,8 @@
 ) %7B%0A
-      // keep link with original model%0A      model = newArr;%0A
     
@@ -2322,16 +2322,23 @@
 odel');%0A
+      %0A
       //
@@ -2344,16 +2344,22 @@
 / local 
+scope 
 var stor
@@ -2392,55 +2392,8 @@
 del%0A
-      // scope.checked - will be set in $watch%0A
     

remove local var `model`