'use strict';


/* Add this to the skia namespace */
var skia = skia || {};
(function (ns) {
  // c contains all constants. Primarily relating to backend resources.
  // They need to match the definitions in go/skiacorrectness/main.go
  ns.c = {
    // PREFIX_URL is the prefix to all backend request to JSON resources.
    PREFIX_URL: '/rest',

    // URLs exposed by the backend to retrieve JSON data.
    URL_COUNTS: '/counts',
    URL_TRIAGE: '/triage',
    URL_STATUS: '/status',

    URL_LOGIN_STATUS: '/loginstatus',
    URL_LOGOUT: '/logout',

    // The triage labels need to match the values in golden/go/types/types.go
    UNTRIAGED: 0,
    POSITIVE: 1,
    NEGATIVE: 2,

    // Key in parameters that identifies a test.
    PRIMARY_KEY_FIELD: 'name',

    CORPUS_FIELD: 'source_type',

    // Param fields to filter.
    PARAMS_FILTER: {
      'source_type': true
    },

    // Query parameters (that are not automatically available via parameters).
    QUERY_COMMIT_START: 'cs',
    QUERY_COMMIT_END: 'ce',

    // Miscellaneous query flags.
    QUERY_HEAD: 'head',
  };

  // List of states - used to cycle through via nextState.
  ns.c.ALL_STATES = [ns.c.UNTRIAGED, ns.c.POSITIVE, ns.c.NEGATIVE];

  // Set of query flags that are not related to parameters or commits.
  ns.c.QUERY_FLAGS = [ns.c.QUERY_HEAD];

    /**
     * Plot is a class that wraps the flot object and exposes draw functions.
     *
     * @param {jQueryElement} element This a jquery element to which the
                                      flot instance to attach to.
     *
     * @return {Plot} instance of Plot class.
     **/

  ns.Plot = function (element) {
    this.element = element;

    // initialize the flot element with empty data.
    this.flotObj = element.plot([], {
      legend: {
        show: true
      },
      xaxis: {
        show: true
      }
    }).data('plot');
  };


  /**
   * setData sets the data that the plot needs to draw and forces a redraw.
   * If ticks is not null it will also set the ticks and reset the x-axis.
   *
     * @param {array} data Array of series understood by Flot. See
     *           https://github.com/flot/flot/blob/master/API.md#data-format
     *
     * @param {array} ticks Array or function that defines the ticks for the
     *                      x-axis.
  */
  ns.Plot.prototype.setData = function(data, ticks) {
    this.flotObj.setData(data);

    // Set the ticks on the x axis if necessary.
    if (ticks) {
      var opt = this.flotObj.getOptions();
      opt.xaxes.forEach(function(axis) {
        axis.ticks = ticks;
      });
    }

    this.redraw();
  };

  /**
  * redraw forces a resize and redraw of the canvas.
  */
  ns.Plot.prototype.redraw = function () {
    // redraw the graph
    this.flotObj.resize();
    this.flotObj.setupGrid();
    this.flotObj.draw();
  }

  /**
   * PlotData is a class that used as the return value of processAllCounts and
   * contains the processed data.
   *  */
  ns.PlotData = function (data, ticks, allAggregates, testDetails) {
    this.plotData = data;
    this.ticks = ticks;
    this.testDetails = testDetails;
    this.allAggregates = allAggregates;
  };

  /**
   * getTicks returns the ticks for the PlotData object at hand.
   */
  ns.PlotData.prototype.getTicks = function (axis) {
    return this.ticks;
  };

  /**
  * TestDetails is a class that contails the aggregated information about
  * a single tests. It is derived from the data returned by the server.
  */
  ns.TestDetails = function (name, counts) {
    this.name = name;
    this.counts = counts;
    this.aggregates = aggregateCounts(counts);
  };

  /**
  * DiffDigestInfo is a helper class to store information about a
  * digest (usually positive) and how it differs from the a given
  * untriaged digest.
  */
  ns.DiffDigestInfo = function (digest, imgUrl, count, paramCounts, diff) {
    this.digest = digest;
    this.imgUrl = imgUrl;
    this.count = count;
    this.paramCounts = paramCounts;
    this.diff = diff;
  };

  /**
  * isIdentical returns true if the current digest is identical
  *             to the untriaged digest.
  */
  ns.DiffDigestInfo.prototype.isIdentical = function () {
    return this.diff.numDiffPixels === 0;
  }

  /**
  * addIndexAsX adds takes an array of numbers and returns an array of
  * datapoints (x,y) where x is the index of the input element y.
  */
  function addIndexAsX(arr) {
    var result = [];
    for(var i=0, len=arr.length; i<len; i++) {
      result.push([i, arr[i]])
    }
    return result;
  }

  /**
  * aggregateCounts sums over the counts contained in an object.
  * Each member in the object is assumed to be an array of numbers.
  *
  * @param { object } countsObj contains attributes where each attribute
  *                   is an array of numbers.
  * @return {object} an array with the same attributes as the input object.
  *                  Each attribute contains the sum of the corresponding
  *                  array.
  */
  function aggregateCounts(countsObj) {
    var result = {};
    var arr;
    for(var k in countsObj) {
      if (countsObj.hasOwnProperty(k)) {
        result[k] = 0;
        arr = countsObj[k];
        for(var i=0,len=arr.length; i < len; i++) {
          result[k] += arr[i];
        }
      }
    }
    return result;
  }

  /**
  * processAllCounts converts the data returned by the server to
  *  an instance of PlotData that can then be used to render the UI
  *  and also serve as input to the Plot class.
  *
  * @param {object} serverData returned from the server containing the
  *                 aggregated values over all tests.
  *
  * @param {string} testName specifies whether we want to get the data
  *                 for a specific test. If null all data are returned.
  *
  * @return {object} instance of PlotData.
  *
  */
  ns.processCounts = function (serverData, testName) {
    // get the counts from the tests.
    var testCounts = [];
    if (testName && serverData.counts.hasOwnProperty(testName)) {
      testCounts.push(new ns.TestDetails(testName, serverData.counts[testName]))
    }
    else {
      for(var tName in serverData.counts) {
        if (serverData.counts.hasOwnProperty(tName)) {
          testCounts.push(new ns.TestDetails(tName, serverData.counts[tName]));
        }
      }
    }

    // assemble the plot data.
    var targetData = testName ? serverData.counts[testName] : serverData.aggregated;
    var data = [];
    for(var k in targetData) {
      if (targetData.hasOwnProperty(k)) {
        data.push({
          label: k,
          lines: {
            show: true,
            steps: true
          },
          data: addIndexAsX(targetData[k])
        });
      }
    }

    return new ns.PlotData(data,
                           serverData.ticks,
                           aggregateCounts(serverData.aggregated),
                           testCounts);
  };



  /**
    getAutoCommitRanges returns a list of decreasing commit ranges
    that can be used to render a simple selection on the screen.
    TODO: Make this adaptive on the backend so that the minimum is not
    5 but whatever number of commits cover all traces aka constitute
    out current knowledge of HEAD.
  */
  var COMMIT_INTERVALS = [100, 50, 20, 15, 10, 5];
  ns.getAutoCommitRanges = function(serverData) {
    var commits = serverData.commits;
    var result = [{ start: commits[0], name: commits.length }];
    for(var i=0, len=COMMIT_INTERVALS.length; i < len; i++) {
      if (commits.length > COMMIT_INTERVALS[i]) {
        result.push({ start: commits[COMMIT_INTERVALS[i]-1], name: COMMIT_INTERVALS[i] });
      }
    }

    return result;
  };

  /**
  * extractTriageData is the central function to pre-process data coming
  *                   from the server.
  */
  ns.extractTriageData = function (serverData, filterParams) {
    var result = [];
    var triageState = {};
    var totalUnt = new Stats(),
        totalPos = new Stats(),
        totalNeg = new Stats();

    for (var i = 0, len = serverData.tests.length; i < len; i++) {
      var untStats = new Stats();
      var posStats = new Stats();
      var negStats = new Stats();
      var positive = ns.getSortedDigests(serverData, 'positive', posStats, i);
      var negative = ns.getSortedDigests(serverData, 'negative', negStats, i);
      var untriaged = ns.getUntriagedSorted(serverData, i, untStats);
      var testName = serverData.tests[i].name;

      // Set the triage state for each digest.
      var add = function(arr, state) {
        for (var i=0, len=arr.length; i<len; i++) {
          triageState[testName][arr[i].digest] = state;
        }
      };

      triageState[testName] = {};
      add(positive[0], ns.c.POSITIVE);
      add(negative[0], ns.c.NEGATIVE);
      add(untriaged, ns.c.UNTRIAGED);

      result.push({
        name: testName,
        untriaged: untriaged,
        positive:  positive[0],
        positiveMap: positive[1],
        negative:  negative[0],
        negativeMap: negative[1],
        untStats:  untStats,
        posStats:  posStats,
        negStats:  negStats
      });

      totalPos.add(posStats);
      totalNeg.add(negStats);
      totalUnt.add(untStats);
    }

    return {
      tests: result,
      allParams: ns.getSortedParams(serverData, filterParams),
      triageState: triageState,
      commitRanges: ns.getAutoCommitRanges(serverData),
      untStats: totalUnt,
      posStats: totalPos,
      negStats: totalNeg
    };
  };

  /**
  * extractTriageListData returns test data across tests from data returned
  * by the server. Currently shows number of unques digests for each test.
  */
  ns.extractTriageListData = function (serverData) {
    var result = [];
    var tests = serverData.tests;
    for (var i=0, len=tests.length; i < len; i++) {
      var t = tests[i];
      var  posK = ns.keys(t.positive);
      var  negK = ns.keys(t.negative);
      var  untK = ns.keys(t.untriaged);
      var showPos = (posK.length > 0) && t.positive[posK[0]];
      var showUnt = (untK.length > 0) && t.untriaged[untK[0]];
      var showDif = (posK.length > 0) && (untK.length > 0);

      var untStats = new Stats();
      var untriaged = ns.getUntriagedSorted(serverData, i, untStats);

      // Return the stats element and the list of untriaged Digests.
      result.push({
        name: t.name,
        posLen: posK.length,
        negLen: negK.length,
        untLen: untK.length,
        showPos: showPos,
        showUnt: showUnt,
        showDif: showDif,
        untriaged: untriaged
      });
    }

    result.sort(function(a,b) {
      return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
    });

    return {
      tests: result,
      allParams: ns.getSortedParams(serverData, false),
      commitRanges: ns.getAutoCommitRanges(serverData)
    };
  };

  /**
  * Stats is a helper class to hold counts about a set of digests.
  */
  function Stats(total, unique) {
    this.total = total || 0;
    this.unique = unique || 0;
  }

  Stats.prototype.set = function (total, unique) {
    this.total = total;
    this.unique = unique;
  };

  Stats.prototype.add = function (statsObj) {
    this.total += statsObj.total;
    this.unique += statsObj.unique;
  };

  /**
  *  getUntriagedSorted returns the untriaged digests sorted by largest
  *  deviation from a positively labeled digest. It processes the data
  *  directly returned by the backend.
  *  It also resolves the references to the positive digests contained in
  *  the diff metrics.
  */
  ns.getUntriagedSorted = function(serverData, testIdx, stats) {
    var unt = robust_get(serverData, ['tests', testIdx, 'untriaged']);
    if (!unt) {
      return [];
    }

    var posd, d;
    var result = [];
    var positive = serverData.tests[testIdx].positive;
    var hasPos = false;
    var total = 0;

    for (var digest in unt) {
      if (unt.hasOwnProperty(digest)) {
        total += unt[digest].count;
        var posDiffs = [];
        var useDiffs = robust_get(unt, [digest, 'diffs']);
        if (useDiffs) {
          for(var i=0, len=useDiffs.length; i < len; i++) {
            // TODO (stephana): Fill in expanding the diff information.
            // This will be done once triaging works. So we can test it
            // with real data.
            d = useDiffs[i];
            if (d) {
              posd = positive[d.posDigest];
              posDiffs.push(new ns.DiffDigestInfo(d.posDigest, posd.imgUrl,
                                             posd.count, posd.paramCounts, d));
            }
          }
        }
        hasPos = hasPos || (posDiffs.length > 0);

        // Inject the digest and the augmented positive diffs.
        unt[digest].digest = digest;
        unt[digest].positiveDiffs = posDiffs;
        unt[digest].paramCounts = ns.filterObject(unt[digest].paramCounts, ns.c.PARAMS_FILTER);
        result.push(unt[digest]);
      }
    }


    if (hasPos) {
      result = result.filter(function(a) {
        return a.positiveDiffs.length > 0;
      });
    }
    stats.set(total, result.length);

    // Sort the result increasing by pixel difference or
    // decreasing by counts if there are no positives.
    var sortFn;
    if (hasPos) {
      sortFn = function (a,b) {
        return a.positiveDiffs[0].diff.numDiffPixels - b.positiveDiffs[0].diff.numDiffPixels;
      };
    } else {
      sortFn = function (a,b) { return b.count - a.count; };
    }
    result.sort(sortFn);

    return result;
  };

  /**
  * getSortedPositivesFromUntriaged returns the list of positively labeled
  * digests. It assumes that 'untriagedRec' was generated by a call to
  * getUntriagedSorted(...).
  */
  ns.getSortedPositivesFromUntriaged = function (untriagedRec) {
    if (untriagedRec && untriagedRec.positiveDiffs && untriagedRec.positiveDiffs.length > 0) {
      return untriagedRec.positiveDiffs;
    }

    return [];
  };

  /**
  * getSortedDigests returns a list of digests with the given digestClass
  * from the data returnded by the backend. This is to be used when there are no
  * untriaged digests.
  */
  ns.getSortedDigests= function (serverData, digestClass, stats, idx) {
    var targetDigests = robust_get(serverData, ['tests', idx, digestClass]);
    if (!targetDigests)  {
      return [[], {}];
    }

    var result = [];
    var total = 0;
    for (var digest in targetDigests) {
      if (targetDigests.hasOwnProperty(digest)) {
        total += targetDigests[digest].count;
        // Inject the digest into the object.
        targetDigests[digest].digest = digest;
        targetDigests[digest].paramCounts = ns.filterObject(
                        targetDigests[digest].paramCounts, ns.c.PARAMS_FILTER);
        result.push(targetDigests[digest]);
      }
    }

    stats.set(total, result.length);

    // Sort the result in decreasing order of their occurences.
    result.sort(function (a,b) {
      a.count - b.count;
    });

    return [result, targetDigests];
  };

  /**
  * getSortedParams returns all parameters and the union of their values as a
  * (nested) sorted Array in the format:
  *       [[param1, [val1, val2, ...],
           [param2, [val3, val4, ...], ... ]]]
  */
  ns.getSortedParams = function (serverData, filter) {
    var result = [];
    for(var k in serverData.allParams) {
      if (serverData.allParams.hasOwnProperty(k) && (!filter || !ns.c.PARAMS_FILTER[k])) {
          serverData.allParams[k].sort();
          result.push([k, serverData.allParams[k]]);
      }
    }

    result.sort(function(a,b){
      return (a[0] < b[0]) ? -1 : (a[0] > b[0]) ? 1 : 0;
    });

    return result;
  };

  /**
  * filterQueryByParams returns a suboject of query only containing
  * the members that are in sortedParams. sortedParams is assumed to be
  * the same format as returned by the getSortedParams function.
  */

  ns.filterQueryByParams = function (query, sortedParams) {
    if  (!sortedParams || !query) {
      return {};
    }

    var result = {};
    for (var i=0, len=sortedParams.length; i<len; i++) {
      if (query.hasOwnProperty(sortedParams[i][0])) {
        result[sortedParams[i][0]] = query[sortedParams[i][0]];
      }
    }
    return result;
  }

  function robustArrayOrStr(obj, key, idx) {
    if (!obj) {
      return obj;
    }

    if (!obj[key]) {
      return obj[key];
    }

    if (Array.isArray(obj[key])) {
      return obj[key][idx];
    }
    return obj[key];
  }

  ns.splitQuery = function (query, allParams) {
    var paramQuery = ns.filterQueryByParams(query, allParams);
    var flagsQuery = ns.subObject(query, ns.c.QUERY_FLAGS);

    var crq = {};
    crq[ns.c.QUERY_COMMIT_START] = robustArrayOrStr(query, ns.c.QUERY_COMMIT_START, 0) || "";
    crq[ns.c.QUERY_COMMIT_END] = robustArrayOrStr(query, ns.c.QUERY_COMMIT_END, 0) || "";

    return {
      paramQuery: paramQuery,
      commitRangeQuery: crq,
      flagsQuery: flagsQuery,
    };
  }

  // flatQueryValueOr returns the value in query identified by
  // key. If that value is an array it will return the first element
  // in the array. If the value is a string it will return the string.
  // If key doesn't exist or the array is empty the defaultValue will be
  // returned.
  ns.flatQueryValueOr = function(query, key, defaultVal) {
    var val = query[key];

    if (!val) {
      return defaultVal;
    }

    if (Array.isArray(val)) {
      if (val.length > 0) {
        return val[0];
      }
      return defaultVal;
    }
    return val;
  };

  // sortedKeys returns the keys of the object in sorted order.
  ns.sortedKeys = function(obj) {
    var result = ns.keys(obj);
    result.sort();
    return result;
  };

  // keys returns the keys of an object.
  ns.keys = function(obj) {
    if (obj.keys) {
      return keys();
    }
    var result = [];
    for(var k in obj) {
      if (obj.hasOwnProperty(k)) {
        result.push(k);
      }
    }
    return result;
  };

  // Returns an object as an array sorted by keys. This assumes that the keys
  // are strings.
  ns.getSortedObject = function(obj) {
    var result = [];
    for(var k in obj) {
      if (obj.hasOwnProperty(k)) {
        result.push([k, obj[k]]);
      }
    }

    result.sort(function(a,b) {
      return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
    });

    return result;
  };

  /**
  * getCombinedParamsTable takes a variable number of paramCounts and
  * combines them into a multi dimensional array to be displayed as a
  * table. The output format is:
  *    [
  *     { p: 'paramName1', c: [['val1','val2'],['val3', 'val4']] },
  *     { p: 'paramName2', c: [['valx','valy'],['val3', 'val4']] },
  *     { p: 'paramName3', c: [['val1','val2'],['val3', 'val4']] },
  *     { p: 'paramName4', c: [['val1','val2'],['val3', 'val4']] }
  *    ]
  * The array is sorted by values of 'p'.
  */
  ns.getCombinedParamsTable = function ( _ ) {
    var combined = {};
    for(var i=0, len=arguments.length; (i<len) && arguments[i]; i++) {
      var params = arguments[i];
      for(var k in params) {
        if (params.hasOwnProperty(k)) {
          if (!combined[k]) {
            combined[k] = [];
          }
          combined[k][i] = ns.sortedKeys(params[k]);
        }
      }
    }

    var result = [];
    for(var k in combined) {
      if (combined.hasOwnProperty(k)) {
        result.push({p: k, c: combined[k]});
      }
    }

    result.sort(function(a,b) {
      return (a.p < b.p) ? -1 : (a.p > b.p) ? 1 : 0;
    });

    return result;
  };

  /**
  * nextState returns the next state in the order defined by ALL_STATES.
  */
  ns.nextState = function(state) {
    var idx = (ns.c.ALL_STATES.indexOf(state) + 1) % ns.c.ALL_STATES.length;
    return ns.c.ALL_STATES[idx];
  };

  /**
  * getNumArray returns an array of numbers of the given length and each
  * element is initialized with initVal. If initVal is omitted, 0 (zero)
  * is used instead.
  */
  ns.getNumArray = function(len, initVal) {
    if (!initVal) {
      initVal = 0;
    }

    var result = [];
    for(var i =0; i < len; i++) {
      result.push(initVal);
    }

    return result;
  };

  /**
  * updateDelta updates the given delta between changed and original for the
  * given testname. If testName evaluates to false the deltas for all tests
  * are calculated. It returns the number of changes this delta would result
  * in.
  */
  ns.updateDelta = function (changed, original, delta, testName) {
    var useTestNames = (testName) ? [testName] : ns.keys(changed);
    var testDelta, testCount, tn;

    for (var i = 0, len = useTestNames.length; i < len; i++) {
      tn = useTestNames[i];
      if (changed.hasOwnProperty(tn)) {
        testDelta = {};
        testCount = 0;

        for (var k in changed[tn]) {
          if (changed[tn].hasOwnProperty(k) &&
              original[tn].hasOwnProperty(k) &&
              (changed[tn][k] !== original[tn][k])) {
            testDelta[k] = changed[tn][k];
            testCount++;
          }
        }

        delta[tn] = {
          delta: testDelta,
          count: testCount
        };
      }
    }

    var pendingCount = 0;
    for(var k in delta) {
      if (delta.hasOwnProperty(k)) {
        pendingCount += delta[k].count;
      }
    }

    return pendingCount;
  };

  /**
  * filterObject returns a copy of 'obj' without the members that
  *              are also members in 'exclude'.
  */
  ns.filterObject = function(obj, exclude) {
    var result = {};
    for(var k in obj) {
      if (obj.hasOwnProperty(k) && !exclude[k]) {
        result[k] = obj[k];
      }
    }

    return result;
  };

  /**
  * subObject returns a new object with only the members that are
  * also in include which is expected to be an array of strings.
  */
  ns.subObject = function(obj, include) {
    var result = {};
    for (var i=0, len=include.length; i<len; i++) {
      if (obj.hasOwnProperty(include[i])) {
        result[include[i]] = obj[include[i]];
      }
    }
    return result;
  };

  /**
  * unionObject returns a new object with the union of all the members
  * of the arbibrary number of objects that are supplied.
  */
  ns.unionObject = function( _ ) {
    var result = {};
    for(var i=0, len=arguments.length; i<len; i++) {
      for(var k in arguments[i]) {
        if (arguments[i].hasOwnProperty(k)) {
          result[k] = arguments[i][k];
        }
      }
    }
    return result;
  }

  /**
  * TriageDigestReq is a container type for sending labeled digests to the
  * backend. It matches the input parameters of the triageDigestsHandler in
  * 'go/skiacorrectness/main.go'.
  */

  ns.TriageDigestReq = function () {
  };

  /**
  * addDigestLabel is a convenience method to add digests and their label to the
  * the instance.
  */
  ns.TriageDigestReq.prototype.add = function (testName, digest, label) {
    this[testName] = this[testName] || {};
    this[testName][digest] = label;
  };

  /////////////////////////////////////////////////////////////////
  // Generic utility functions.
  /////////////////////////////////////////////////////////////////
  /*
  * isEmpty returns true if the provided object is empty and false
  *         otherwise.
  */
  ns.isEmpty = function (obj) {
    for (var k in obj) {
      if (obj.hasOwnProperty(k)) {
        return false;
      }
    }
    return true;
  };

  /*
  */
  ns.extractQueryString = function (url) {
    var idx = url.indexOf('?');
    return (idx === -1) ? '' : url.substring(idx);
  };

  /////////////////////////////////////////////////////////////////
  // Utility functions that are not exposed in the namespace.
  /////////////////////////////////////////////////////////////////

  /**
   * robust_get finds a sub object within 'obj' by following the path
   * in 'idx'. It will not throw an error if any sub object is missing
   * but instead return 'undefined'.
   **/
  function robust_get(obj, idx) {
    if (!idx) {
      return;
    }

    for(var i=0, len=idx.length; i<len; i++) {
      if ((typeof obj === 'undefined') || (typeof idx[i] === 'undefined')) {
        return;  // returns 'undefined'
      }

      obj = obj[idx[i]];
    }

    return obj;
  }


})(skia);
