"use strict";

angular.module('arethusa.depTree').directive('unusedTokenHighlighter', [
  'state',
  function(state) {
    return {
      restrict: 'A',
      scope: {
        highlightMode: '@unusedTokenHighlighter',
        style: '=unusedTokenStyle'
      },
      link: function(scope, element, attrs) {
        var unusedTokens;
        var headWatches = [];
        var style = scope.style || { "background-color": "rgb(255, 216, 216)" }; // a very light red
        var highlightMode = !!scope.highlightMode;
        scope.s = state;

        function tokensWithoutHeadCount() {
          return state.countTokens(function (token) {
            return hasNoHead(token);
          });
        }

        function hasNoHead(token) {
          return !(token.head || {}).id;
        }

        function checkIfUnused(token, id) {
          if (hasNoHead(token)) {
            scope.unusedCount++;
            unusedTokens[id] = true;
          }
        }

        function findUnusedTokens() {
          angular.forEach(state.tokens, checkIfUnused);
        }

        function initHeadWatch(token, id) {
          var childScope = scope.$new();
          childScope.head = token.head;
          childScope.id   = id;
          childScope.$watch('head.id', function(newVal, oldVal) {
            if (newVal !== oldVal) {
              if (newVal) {
                // Check if the token was used before!
                if (!oldVal) {
                  scope.unusedCount--;
                  delete unusedTokens[id];
                  if (highlightMode) removeStyle(id);
                }
              } else {
                scope.unusedCount++;
                unusedTokens[id] = true;
                if (highlightMode) state.addStyle(id, style);
              }
            }
          });
          headWatches.push(childScope);
        }

        function initHeadWatches() {
          destroyOldHeadWatches();
          angular.forEach(state.tokens, initHeadWatch);
        }

        function destroyOldHeadWatches() {
          angular.forEach(headWatches, function(childScope, i) {
            childScope.$destroy();
          });
          headWatches = [];
        }


        function init() {
          scope.total = state.totalTokens;
          scope.unusedCount = 0;
          unusedTokens = {};
          findUnusedTokens();
          initHeadWatches();
          if (highlightMode) applyHighlighting();
        }

        function applyHighlighting() {
          angular.forEach(unusedTokens, function(val, id) {
            state.addStyle(id, style);
          });
        }

        function removeStyle(id) {
          var styles = Object.keys(style);
          state.removeStyle(id, styles);
        }

        function unapplyHighlighting() {
          angular.forEach(unusedTokens, function(val, id) {
            removeStyle(id);
          });
        }

        element.bind('click', function() {
          scope.$apply(function() {
            if (highlightMode) {
              unapplyHighlighting();
            } else {
              applyHighlighting();
            }
          });
          highlightMode = !highlightMode;
        });

        scope.$watch('s.tokens', function(newVal, oldVal) {
          init();
        });

        scope.$on('tokenAdded', function(event, token) {
          var id = token.id;
          scope.total++;
          checkIfUnused(token, id);
          initHeadWatch(token, id);
        });

        scope.$on('tokenRemoved', function(event, token) {
          scope.total--;
        });
      },
      template: '{{ unusedCount }} of {{ total }} unused'
    };
  }
]);

@@ -331,38 +331,8 @@
 ns;%0A
-        var headWatches = %5B%5D;%0A
     
@@ -1041,179 +1041,14 @@
     
-function initHeadWatch(token, id) %7B%0A          var childScope = scope.$new();%0A          childScope.head = token.head;%0A          childScope.id   = id;%0A          childScop
+stat
 e.
-$
 watc
@@ -1075,32 +1075,39 @@
 n(newVal, oldVal
+, event
 ) %7B%0A            
@@ -1108,39 +1108,33 @@
     
-  if (newVal !== oldVal) %7B%0A    
+var id = event.token.id;%0A
     
@@ -1149,28 +1149,24 @@
  (newVal) %7B%0A
-    
             
@@ -1212,28 +1212,24 @@
             
-    
 if (!oldVal)
@@ -1227,28 +1227,24 @@
 (!oldVal) %7B%0A
-    
             
@@ -1280,20 +1280,16 @@
         
-  
-  
 delete u
@@ -1305,20 +1305,16 @@
 ns%5Bid%5D;%0A
-    
         
@@ -1351,28 +1351,24 @@
 eStyle(id);%0A
-    
             
@@ -1371,36 +1371,32 @@
     %7D%0A          
-    
 %7D else %7B%0A       
@@ -1380,36 +1380,32 @@
        %7D else %7B%0A
-    
             scop
@@ -1425,36 +1425,32 @@
 ++;%0A            
-  
-  
 unusedTokens%5Bid%5D
@@ -1454,28 +1454,24 @@
 id%5D = true;%0A
-    
             
@@ -1530,427 +1530,21 @@
     
-    %7D%0A            %7D%0A          %7D);%0A          headWatches.push(childScope);%0A        %7D%0A%0A        function initHeadWatches() %7B%0A          destroyOldHeadWatches();%0A          angular.forEach(state.tokens, initHeadWatch);%0A        %7D%0A%0A        function destroyOldHeadWatches() %7B%0A          angular.forEach(headWatches, function(childScope, i) %7B%0A            childScope.$destroy();%0A          %7D);%0A          headWatches = %5B%5D;%0A        %7D%0A
+%7D%0A        %7D);
 %0A%0A  
@@ -1706,37 +1706,8 @@
 ();%0A
-          initHeadWatches();%0A
     
@@ -2741,44 +2741,8 @@
 d);%0A
-          initHeadWatch(token, id);%0A
     

Refactor uTH to use the new and mighty state.watch()