/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/iron-selector/iron-selector';
import '../../shared/gr-button/gr-button';
import {sharedStyles} from '../../../styles/shared-styles';
import {css, html, LitElement} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {ifDefined} from 'lit/directives/if-defined.js';
import {IronSelectorElement} from '@polymer/iron-selector/iron-selector';
import {
  LabelNameToInfoMap,
  QuickLabelInfo,
  DetailedLabelInfo,
} from '../../../types/common';
import {assertIsDefined, hasOwnProperty} from '../../../utils/common-util';
import {Label} from '../../../utils/label-util';
import {LabelNameToValuesMap} from '../../../api/rest-api';
import {fire} from '../../../utils/event-util';
import {LabelsChangedDetail} from '../../../api/change-reply';

declare global {
  interface HTMLElementTagNameMap {
    'gr-label-score-row': GrLabelScoreRow;
  }
  interface HTMLElementEventMap {
    'labels-changed': CustomEvent<LabelsChangedDetail>;
  }
}

@customElement('gr-label-score-row')
export class GrLabelScoreRow extends LitElement {
  @query('#labelSelector')
  labelSelector?: IronSelectorElement;

  @property({type: Object})
  label: Label | undefined | null;

  @property({type: Object})
  labels?: LabelNameToInfoMap;

  @property({type: String, reflect: true})
  name?: string;

  @property({type: Object})
  permittedLabels: LabelNameToValuesMap | undefined | null;

  @property({type: Array})
  orderedLabelValues?: number[];

  @state()
  private selectedValueText = 'No value selected';

  static override get styles() {
    return [
      sharedStyles,
      css`
        .labelNameCell,
        .buttonsCell,
        .selectedValueCell {
          padding: var(--spacing-s) var(--spacing-m);
          display: table-cell;
        }
        /* We want the :hover highlight to extend to the border of the dialog. */
        .labelNameCell {
          padding-left: var(--label-score-padding-left, 0);
          width: 160px;
        }
        .selectedValueCell {
          padding-right: var(--spacing-xl);
        }
        /* This is a trick to let the selectedValueCell take the remaining width. */
        .labelNameCell,
        .buttonsCell {
          white-space: nowrap;
        }
        .selectedValueCell {
          width: 52%;
        }
        .labelMessage {
          color: var(--deemphasized-text-color);
        }
        gr-button {
          min-width: 42px;
          box-sizing: border-box;
          --vote-text-color: var(--vote-chip-unselected-text-color);
        }
        gr-button.iron-selected {
          --vote-text-color: var(--vote-chip-selected-text-color);
        }
        gr-button::part(paper-button) {
          padding: 0 var(--spacing-m);
          background-color: var(
            --button-background-color,
            var(--table-header-background-color)
          );
          border-color: var(--vote-chip-unselected-outline-color);
        }
        gr-button.iron-selected::part(paper-button) {
          border-color: transparent;
        }
        gr-button {
          --button-background-color: var(--vote-chip-unselected-color);
        }
        gr-button[data-vote='max'].iron-selected {
          --button-background-color: var(--vote-chip-selected-positive-color);
        }
        gr-button[data-vote='positive'].iron-selected {
          --button-background-color: var(--vote-chip-selected-positive-color);
        }
        gr-button[data-vote='neutral'].iron-selected {
          --button-background-color: var(--vote-chip-selected-neutral-color);
        }
        gr-button[data-vote='negative'].iron-selected {
          --button-background-color: var(--vote-chip-selected-negative-color);
        }
        gr-button[data-vote='min'].iron-selected {
          --button-background-color: var(--vote-chip-selected-negative-color);
        }
        gr-button > gr-tooltip-content {
          margin: 0px -10px;
          padding: 0px 10px;
        }
        .placeholder {
          display: inline-block;
          width: 42px;
          height: 1px;
        }
        .placeholder::before {
          content: ' ';
        }
        .selectedValueCell {
          color: var(--deemphasized-text-color);
          font-style: italic;
        }
        .selectedValueCell.hidden {
          display: none;
        }
        @media only screen and (max-width: 50em) {
          .selectedValueCell {
            display: none;
          }
        }
      `,
    ];
  }

  override render() {
    return html`
      <span class="labelNameCell" id="labelName" aria-hidden="true"
        >${this.label?.name ?? ''}</span
      >
      ${this.renderButtonsCell()} ${this.renderSelectedValue()}
    `;
  }

  private renderButtonsCell() {
    return html`
      <div class="buttonsCell">
        ${this.renderBlankItems('start')} ${this.renderLabelSelector()}
        ${this.renderBlankItems('end')}
      </div>
    `;
  }

  // Render blank cells so that all same value votes are aligned
  private renderBlankItems(position: string) {
    const blankItemCount = this.computeBlankItemsCount(position);
    return Array.from({length: blankItemCount})
      .fill('')
      .map(
        () => html`
          <span class="placeholder" data-label=${this.label?.name ?? ''}>
          </span>
        `
      );
  }

  private renderLabelSelector() {
    return html`
      <iron-selector
        id="labelSelector"
        .attrForSelected=${'data-value'}
        selected=${ifDefined(this._computeLabelValue())}
        @selected-item-changed=${this.setSelectedValueText}
        role="radiogroup"
        aria-labelledby="labelName"
      >
        ${this.renderPermittedLabels()}
      </iron-selector>
    `;
  }

  private renderPermittedLabels() {
    const items = this.computePermittedLabelValues();
    return items.map(
      (value, index) => html`
        <gr-button
          role="button"
          title=${ifDefined(this.computeLabelValueTitle(value))}
          data-vote=${this._computeVoteAttribute(
            Number(value),
            index,
            items.length
          )}
          data-name=${ifDefined(this.label?.name)}
          data-value=${value}
          aria-label=${value}
          voteChip
          flatten
        >
          <gr-tooltip-content
            has-tooltip
            light-tooltip
            title=${ifDefined(this.computeLabelValueTitle(value))}
          >
            ${value}
          </gr-tooltip-content>
        </gr-button>
      `
    );
  }

  private renderSelectedValue() {
    return html`
      <div class="selectedValueCell">
        <span id="selectedValueLabel">${this.selectedValueText}</span>
      </div>
    `;
  }

  get selectedItem(): IronSelectorElement | undefined {
    if (!this.labelSelector) {
      return undefined;
    }
    return this.labelSelector.selectedItem as IronSelectorElement;
  }

  get selectedValue() {
    if (!this.labelSelector) {
      return undefined;
    }
    return this.labelSelector.selected;
  }

  setSelectedValue(value: string) {
    // The selector may not be present if it’s not at the latest patch set.
    if (!this.labelSelector) {
      return;
    }
    this.labelSelector.select(value);
  }

  // Private but used in tests.
  computeBlankItemsCount(side: string) {
    if (
      !this.label ||
      !this.permittedLabels?.[this.label.name] ||
      !this.permittedLabels[this.label.name].length ||
      !this.orderedLabelValues?.length
    ) {
      return 0;
    }
    const orderedLabelValues = this.orderedLabelValues;
    const permittedLabel = this.permittedLabels[this.label.name];
    // How many empty cells need to be rendered to the left before showing
    // the first value of the label range. If min value of the label is -1 and
    // overall min possible is -2 then we render one empty cell. If overall min
    // is -1 then we don't render any empty cell.
    if (side === 'start') {
      return Number(permittedLabel[0]) - orderedLabelValues[0];
    }
    // How many empty cells need to be rendered to the right after showing the
    // last value of the label range. If max value is +1 and overall max value
    // is +2 we add one empty cell to the right.
    return (
      orderedLabelValues[orderedLabelValues.length - 1] -
      Number(permittedLabel[permittedLabel.length - 1])
    );
  }

  private getLabelValue() {
    assertIsDefined(this.labels);
    assertIsDefined(this.label);
    assertIsDefined(this.permittedLabels);
    if (this.label.value) {
      return this.label.value;
    } else if (
      hasOwnProperty(this.labels[this.label.name], 'default_value') &&
      hasOwnProperty(this.permittedLabels, this.label.name)
    ) {
      // default_value is an int, convert it to string label, e.g. "+1".
      return this.permittedLabels[this.label.name].find(
        value =>
          Number(value) ===
          (this.labels![this.label!.name] as QuickLabelInfo).default_value
      );
    }
    return;
  }

  /**
   * Private but used in tests.
   * Maps the label value to exactly one of: min, max, positive, negative,
   * neutral. Used for the 'data-vote' attribute, because we don't want to
   * interfere with <iron-selector> using the 'class' attribute for setting
   * 'iron-selected'.
   */
  _computeVoteAttribute(value: number, index: number, totalItems: number) {
    if (value < 0 && index === 0) {
      return 'min';
    } else if (value < 0) {
      return 'negative';
    } else if (value > 0 && index === totalItems - 1) {
      return 'max';
    } else if (value > 0) {
      return 'positive';
    } else {
      return 'neutral';
    }
  }

  // Private but used in tests.
  _computeLabelValue() {
    if (!this.labels || !this.permittedLabels || !this.label) {
      return undefined;
    }

    if (!this.labels[this.label.name]) {
      return undefined;
    }
    const labelValue = this.getLabelValue();
    const permittedLabel = this.permittedLabels[this.label.name];
    const len = permittedLabel ? permittedLabel.length : 0;
    for (let i = 0; i < len; i++) {
      const val = permittedLabel[i];
      if (val === labelValue) {
        return val;
      }
    }
    return undefined;
  }

  private setSelectedValueText = (e: Event) => {
    // Needed because when the selected item changes, it first changes to
    // nothing and then to the new item.
    const selectedItem = (e.target as IronSelectorElement)
      .selectedItem as HTMLElement;
    if (!selectedItem) {
      return;
    }
    if (!this.labelSelector?.items) {
      return;
    }
    for (const item of this.labelSelector.items) {
      if (selectedItem === item) {
        item.setAttribute('aria-checked', 'true');
      } else {
        item.removeAttribute('aria-checked');
      }
    }
    this.selectedValueText = selectedItem.getAttribute('title') || '';
    const name = selectedItem.dataset['name'];
    const value = selectedItem.dataset['value'];
    if (name && value) fire(this, 'labels-changed', {name, value});
  };

  private computePermittedLabelValues() {
    if (!this.permittedLabels || !this.label) {
      return [];
    }

    return this.permittedLabels[this.label.name] || [];
  }

  // private but used in tests
  computeLabelValueTitle(value: string) {
    if (!this.labels || !this.label) return '';
    const label = this.labels[this.label.name] as DetailedLabelInfo;
    if (label && label.values) {
      // In case the user already voted a certain value and then selects 0
      // we should show "Reset Vote" instead of "No Value selected"
      if (
        Number(value) === 0 &&
        this.label.value &&
        Number(this.label.value) !== 0
      ) {
        return 'Reset Vote';
      }
      // TODO(TS): maybe add a type guard for DetailedLabelInfo and
      // QuickLabelInfo
      return label.values[value];
    } else {
      return '';
    }
  }
}
