/**
 * @license
 * 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.
 */
import '../gr-label-score-row/gr-label-score-row';
import '../../../styles/shared-styles';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-label-scores_html';
import {customElement, property} from '@polymer/decorators';
import {hasOwnProperty} from '../../../utils/common-util';
import {
  LabelNameToValueMap,
  ChangeInfo,
  AccountInfo,
  DetailedLabelInfo,
  LabelNameToInfoMap,
  LabelNameToValuesMap,
} from '../../../types/common';
import {
  GrLabelScoreRow,
  Label,
  LabelValuesMap,
} from '../gr-label-score-row/gr-label-score-row';
import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces';
import {appContext} from '../../../services/app-context';
import {labelCompare} from '../../../utils/label-util';
import {Execution} from '../../../constants/reporting';

@customElement('gr-label-scores')
export class GrLabelScores extends PolymerElement {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Array, computed: '_computeLabels(change.labels.*, account)'})
  _labels: Label[] = [];

  @property({type: Object, observer: '_computeColumns'})
  permittedLabels?: LabelNameToValueMap;

  @property({type: Object})
  change?: ChangeInfo;

  @property({type: Object})
  account?: AccountInfo;

  @property({type: Object})
  _labelValues?: LabelValuesMap;

  private readonly reporting = appContext.reportingService;

  getLabelValues(includeDefaults = true): LabelNameToValuesMap {
    const labels: LabelNameToValuesMap = {};
    if (this.shadowRoot === null || !this.change) {
      return labels;
    }
    for (const label of Object.keys(this.permittedLabels ?? {})) {
      const selectorEl = this.shadowRoot.querySelector(
        `gr-label-score-row[name="${label}"]`
      ) as null | GrLabelScoreRow;
      if (!selectorEl?.selectedItem) continue;

      const selectedVal =
        typeof selectorEl.selectedValue === 'string'
          ? Number(selectorEl.selectedValue)
          : selectorEl.selectedValue;

      if (selectedVal === undefined) continue;

      const defValNum = this._getDefaultValue(this.change.labels, label);
      if (includeDefaults || selectedVal !== defValNum) {
        labels[label] = selectedVal;
      }
    }
    return labels;
  }

  _getStringLabelValue(
    labels: LabelNameToInfoMap,
    labelName: string,
    numberValue?: number
  ): string {
    const detailedInfo = labels[labelName] as DetailedLabelInfo;
    if (detailedInfo.values) {
      for (const labelValue of Object.keys(detailedInfo.values)) {
        if (Number(labelValue) === numberValue) {
          return labelValue;
        }
      }
    }
    const stringVal = `${numberValue}`;
    this.reporting.reportExecution(Execution.REACHABLE_CODE, {
      value: stringVal,
      id: 'label-value-not-found',
    });
    return stringVal;
  }

  _getDefaultValue(labels?: LabelNameToInfoMap, labelName?: string) {
    if (!labelName || !labels?.[labelName]) return undefined;
    const labelInfo = labels[labelName] as DetailedLabelInfo;
    return labelInfo.default_value;
  }

  _getVoteForAccount(
    labels: LabelNameToInfoMap | undefined,
    labelName: string,
    account?: AccountInfo
  ): string | null {
    if (!labels) return null;
    const votes = labels[labelName] as DetailedLabelInfo;
    if (votes.all && votes.all.length > 0) {
      for (let i = 0; i < votes.all.length; i++) {
        // TODO(TS): Replace == with === and check code can assign string to _account_id instead of number
        // eslint-disable-next-line eqeqeq
        if (account && votes.all[i]._account_id == account._account_id) {
          return this._getStringLabelValue(
            labels,
            labelName,
            votes.all[i].value
          );
        }
      }
    }
    return null;
  }

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

  _computeColumns(permittedLabels?: LabelNameToValueMap) {
    if (!permittedLabels) return;
    const labels = Object.keys(permittedLabels);
    const values: Set<number> = new Set();
    for (const label of labels) {
      for (const value of permittedLabels[label]) {
        values.add(Number(value));
      }
    }

    const orderedValues = Array.from(values.values()).sort((a, b) => a - b);

    const labelValues: LabelValuesMap = {};
    for (let i = 0; i < orderedValues.length; i++) {
      labelValues[orderedValues[i]] = i;
    }
    this._labelValues = labelValues;
  }

  _changeIsMerged(changeStatus: string) {
    return changeStatus === 'MERGED';
  }

  _computeLabelAccessClass(
    label?: string,
    permittedLabels?: LabelNameToValueMap
  ) {
    if (!permittedLabels || !label) {
      return '';
    }

    return hasOwnProperty(permittedLabels, label) &&
      permittedLabels[label].length
      ? 'access'
      : 'no-access';
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-label-scores': GrLabelScores;
  }
}
