// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
(function() {
  'use strict';

  Polymer({
    is: 'gr-label-scores',
    properties: {
      _labels: {
        type: Array,
        computed: '_computeLabels(change.labels.*, account)',
      },
      permittedLabels: {
        type: Object,
        observer: '_computeColumns',
      },
      /** @type {?} */
      change: Object,
      _labelValues: Object,
    },

    getLabelValues() {
      const labels = {};
      for (const label in this.permittedLabels) {
        if (!this.permittedLabels.hasOwnProperty(label)) { continue; }

        const selectorEl = this.$$(`gr-label-score-row[name="${label}"]`);
        if (!selectorEl) { continue; }

        // The user may have not voted on this label.
        if (!selectorEl.selectedItem) { continue; }

        const selectedVal = parseInt(selectorEl.selectedValue, 10);

        // Only send the selection if the user changed it.
        let prevVal = this._getVoteForAccount(this.change.labels, label,
            this.account);
        if (prevVal !== null) {
          prevVal = parseInt(prevVal, 10);
        }
        if (selectedVal !== prevVal) {
          labels[label] = selectedVal;
        }
      }
      return labels;
    },

    _getStringLabelValue(labels, labelName, numberValue) {
      for (const k in labels[labelName].values) {
        if (parseInt(k, 10) === numberValue) {
          return k;
        }
      }
      return numberValue;
    },

    _getVoteForAccount(labels, labelName, account) {
      const votes = labels[labelName];
      if (votes.all && votes.all.length > 0) {
        for (let i = 0; i < votes.all.length; i++) {
          if (votes.all[i]._account_id == account._account_id) {
            return this._getStringLabelValue(
                labels, labelName, votes.all[i].value);
          }
        }
      }
      return null;
    },

    _computeLabels(labelRecord) {
      const labelsObj = labelRecord.base;
      if (!labelsObj) { return []; }
      return Object.keys(labelsObj).sort().map(key => {
        return {
          name: key,
          value: this._getVoteForAccount(labelsObj, key, this.account),
        };
      });
    },

    _computeColumns(permittedLabels) {
      const labels = Object.keys(permittedLabels);
      const values = {};
      for (const label of labels) {
        for (const value of permittedLabels[label]) {
          values[parseInt(value, 10)] = true;
        }
      }

      const orderedValues = Object.keys(values).sort((a, b) => {
        return a - b;
      });

      for (let i = 0; i < orderedValues.length; i++) {
        values[orderedValues[i]] = i;
      }
      this._labelValues = values;
    },

    _changeIsMerged(changeStatus) {
      return changeStatus === 'MERGED';
    },
  });
})();
