'use strict';

angular.module('polestar')
  .directive('functionSelect', function(_, consts, vl, Pills, Logger, Schema) {
    return {
      templateUrl: 'components/functionselect/functionselect.html',
      restrict: 'E',
      scope: {
        channel: '=',
        fieldDef: '='
      },
      link: function(scope /*,element, attrs*/) {
        var BIN='bin', RAW='', COUNT='count', maxbins;

        scope.pills = Pills.pills;
        scope.func = {
          selected: RAW,
          list: [RAW]
        };

        function fieldPill() {
          return Pills ? Pills.pills[scope.channel] : null;
        }

        function getFns(type) {

          if (type === 'temporal') {
            return Schema.schema.definitions.TimeUnit.enum;
          }
          return [];
        }

        function getAggrs(type) {
          if(!type) {
            return [COUNT];
          }

          // HACK
          // TODO: make this correct for temporal as well
          if (type === 'quantitative' ){
            return Schema.schema.definitions.AggregateOp.enum;
          }
          return [];
        }

        scope.selectChanged = function() {
          Logger.logInteraction(Logger.actions.FUNC_CHANGE, scope.func.selected);
        };

        // FIXME func.selected logic should be all moved to selectChanged
        // when the function select is updated, propagates change the parent
        scope.$watch('func.selected', function(selectedFunc) {
          var oldPill = fieldPill(),
            pill = _.clone(oldPill),
            type = pill ? pill.type : '';

          if(!pill){
            return; // not ready
          }

          // reset field def
          // HACK: we're temporarily storing the maxbins in the pill
          pill.bin = selectedFunc === BIN ? true : undefined;
          pill.aggregate = getAggrs(type).indexOf(selectedFunc) !== -1 ? selectedFunc : undefined;
          pill.timeUnit = getFns(type).indexOf(selectedFunc) !== -1 ? selectedFunc : undefined;

          if(!_.isEqual(oldPill, pill)){
            Pills.pills[scope.channel] = pill;
            Pills.update(scope.channel);
          }
        });

        // when parent objects modify the field
        scope.$watch('fieldDef', function(pill) {
          if (!pill) {
            return;
          }

          var type = pill.field ? pill.type : '';

          // hack: save the maxbins
          if (pill.bin) {
            maxbins = pill.bin.maxbins;
          }

          var isOrdinalShelf = ['row','column','shape'].indexOf(scope.channel) !== -1,
            isQ = type === vl.type.QUANTITATIVE,
            isT = type === vl.type.TEMPORAL;

          if(pill.field === '*' && pill.aggregate === COUNT){
            scope.func.list=[COUNT];
            scope.func.selected = COUNT;
          } else {
            scope.func.list = ( isOrdinalShelf && (isQ || isT) ? [] : [''])
              .concat(getFns(type))
              .concat(getAggrs(type).filter(function(x) { return x !== COUNT; }))
              // TODO: check supported type based on primitive data?
              .concat(type === 'quantitative' ? ['bin'] : []);

            var defaultVal = (isOrdinalShelf &&
              (isQ && BIN) || (isT && consts.defaultTimeFn)
            ) || RAW;

            var selected = pill.bin ? 'bin' :
              pill.aggregate || pill.timeUnit ||
              defaultVal;

            if (scope.func.list.indexOf(selected) >= 0) {
              scope.func.selected = selected;
            } else {
              scope.func.selected = defaultVal;
            }

          }
        }, true);
      }
    };
  });

@@ -512,110 +512,8 @@
 %7D;%0A%0A
-        function fieldPill() %7B%0A          return Pills ? Pills.pills%5Bscope.channel%5D : null;%0A        %7D%0A%0A
     
@@ -1382,18 +1382,31 @@
 l = 
-fieldPill(
+Pills.get(scope.channel
 ),%0A 
@@ -1970,14 +1970,12 @@
 lls.
-pills%5B
+set(
 scop
@@ -1987,17 +1987,80 @@
 nnel
-%5D =
+,
  pill
-;
+);%0A%0A            // FIXME figure out why we need to manually update
 %0A   

use `Pills.get|set` in `functionselect`