/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/paper-toggle-button/paper-toggle-button';
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-button/gr-button';
import '../gr-rule-editor/gr-rule-editor';
import {css, html, LitElement, PropertyValues} from 'lit';
import {
  toSortedPermissionsArray,
  PermissionArrayItem,
  PermissionArray,
  AccessPermissionId,
} from '../../../utils/access-util';
import {customElement, property, query, state} from 'lit/decorators.js';
import {
  LabelNameToLabelTypeInfoMap,
  LabelTypeInfoValues,
  GroupInfo,
  GitRef,
  RepoName,
} from '../../../types/common';
import {
  AutocompleteQuery,
  GrAutocomplete,
  AutocompleteSuggestion,
} from '../../shared/gr-autocomplete/gr-autocomplete';
import {
  EditablePermissionInfo,
  EditablePermissionRuleInfo,
  EditableRepoAccessGroups,
} from '../gr-repo-access/gr-repo-access-interfaces';
import {getAppContext} from '../../../services/app-context';
import {fire} from '../../../utils/event-util';
import {sharedStyles} from '../../../styles/shared-styles';
import {paperStyles} from '../../../styles/gr-paper-styles';
import {grFormStyles} from '../../../styles/gr-form-styles';
import {menuPageStyles} from '../../../styles/gr-menu-page-styles';
import {when} from 'lit/directives/when.js';
import {
  AutocompleteCommitEvent,
  ValueChangedEvent,
} from '../../../types/events';
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {repeat} from 'lit/directives/repeat.js';

const MAX_AUTOCOMPLETE_RESULTS = 20;

const RANGE_NAMES = ['QUERY LIMIT', 'BATCH CHANGES LIMIT'];

type GroupsWithRulesMap = {[ruleId: string]: boolean};

interface ComputedLabelValue {
  value: number;
  text: string;
}

interface ComputedLabel {
  name: string;
  values: ComputedLabelValue[];
}

interface GroupSuggestion {
  name: string;
  value: GroupInfo;
}

@customElement('gr-permission')
export class GrPermission extends LitElement {
  @property({type: String})
  repo?: RepoName;

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

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

  @property({type: Object})
  permission?: PermissionArrayItem<EditablePermissionInfo>;

  @property({type: Object})
  groups?: EditableRepoAccessGroups;

  @property({type: String})
  section?: GitRef;

  @property({type: Boolean})
  editing = false;

  @state()
  private label?: ComputedLabel;

  @state()
  private groupFilter?: string;

  @state()
  private query: AutocompleteQuery;

  @state()
  rules?: PermissionArray<EditablePermissionRuleInfo | undefined>;

  @state()
  groupsWithRules?: GroupsWithRulesMap;

  @state()
  deleted = false;

  @state()
  originalExclusiveValue?: boolean;

  @query('#groupAutocomplete')
  private groupAutocomplete!: GrAutocomplete;

  private readonly restApiService = getAppContext().restApiService;

  constructor() {
    super();
    this.query = () => this.getGroupSuggestions();
    this.addEventListener('access-saved', () => this.handleAccessSaved());
  }

  override connectedCallback() {
    super.connectedCallback();
    this.setupValues();
  }

  override willUpdate(changedProperties: PropertyValues<GrPermission>): void {
    const oldEditing = changedProperties.get('editing');
    if (oldEditing !== null && oldEditing !== undefined) {
      this.handleEditingChanged(oldEditing);
    }
    if (
      changedProperties.has('permission') ||
      changedProperties.has('labels')
    ) {
      this.label = this.computeLabel();
    }
    if (changedProperties.has('permission')) {
      this.sortPermission(this.permission);
    }
  }

  static override get styles() {
    return [
      sharedStyles,
      paperStyles,
      grFormStyles,
      menuPageStyles,
      css`
        :host {
          display: block;
          margin-bottom: var(--spacing-m);
        }
        .header {
          align-items: baseline;
          display: flex;
          justify-content: space-between;
          margin: var(--spacing-s) var(--spacing-m);
        }
        .rules {
          background: var(--table-header-background-color);
          border: 1px solid var(--border-color);
          border-bottom: 0;
        }
        .editing .rules {
          border-bottom: 1px solid var(--border-color);
        }
        .title {
          margin-bottom: var(--spacing-s);
        }
        #addRule,
        #removeBtn {
          display: none;
        }
        .right {
          display: flex;
          align-items: center;
        }
        .editing #removeBtn {
          display: block;
          margin-left: var(--spacing-xl);
        }
        .editing #addRule {
          display: block;
          padding: var(--spacing-m);
        }
        #deletedContainer,
        .deleted #mainContainer {
          display: none;
        }
        .deleted #deletedContainer {
          align-items: baseline;
          border: 1px solid var(--border-color);
          display: flex;
          justify-content: space-between;
          padding: var(--spacing-m);
        }
        #mainContainer {
          display: block;
        }
      `,
    ];
  }

  override render() {
    if (!this.section || !this.permission) {
      return;
    }
    return html`
      <section
        id="permission"
        class="gr-form-styles ${this.computeSectionClass(
          this.editing,
          this.deleted
        )}"
      >
        <div id="mainContainer">
          <div class="header">
            <span class="title">${this.name}</span>
            <div class="right">
              ${when(
                !this.permissionIsOwnerOrGlobal(
                  this.permission.id ?? '',
                  this.section
                ),
                () => html`
                  <paper-toggle-button
                    id="exclusiveToggle"
                    ?checked=${this.permission?.value.exclusive}
                    ?disabled=${!this.editing}
                    @change=${this.handleValueChange}
                    @click=${this.onTapExclusiveToggle}
                    @tap=${this.onTapExclusiveToggle}
                  ></paper-toggle-button
                  >${this.computeExclusiveLabel(this.permission?.value)}
                `
              )}
              <gr-button
                link=""
                id="removeBtn"
                @click=${this.handleRemovePermission}
                >Remove</gr-button
              >
            </div>
          </div>
          <!-- end header -->
          <div class="rules">
            ${repeat(
              this.rules ?? [],
              rule => rule.id,
              (rule, index) => html`
                <gr-rule-editor
                  .hasRange=${this.computeHasRange(this.name)}
                  .label=${this.label}
                  .editing=${this.editing}
                  .groupId=${rule.id}
                  .groupName=${this.computeGroupName(this.groups, rule.id)}
                  .permission=${this.permission!.id as AccessPermissionId}
                  .rule=${rule}
                  .section=${this.section}
                  @rule-changed=${(e: CustomEvent) =>
                    this.handleRuleChanged(e, index)}
                  @added-rule-removed=${(_: Event) =>
                    this.handleAddedRuleRemoved(index)}
                ></gr-rule-editor>
              `
            )}
            <div id="addRule">
              <gr-autocomplete
                id="groupAutocomplete"
                .text=${this.groupFilter ?? ''}
                @text-changed=${(e: ValueChangedEvent) =>
                  (this.groupFilter = e.detail.value)}
                .query=${this.query}
                placeholder="Add group"
                @commit=${this.handleAddRuleItem}
              >
              </gr-autocomplete>
            </div>
            <!-- end addRule -->
          </div>
          <!-- end rules -->
        </div>
        <!-- end mainContainer -->
        <div id="deletedContainer">
          <span>${this.name} was deleted</span>
          <gr-button link="" id="undoRemoveBtn" @click=${this.handleUndoRemove}
            >Undo</gr-button
          >
        </div>
        <!-- end deletedContainer -->
      </section>
    `;
  }

  setupValues() {
    if (!this.permission) {
      return;
    }
    this.originalExclusiveValue = !!this.permission.value.exclusive;
    this.requestUpdate();
  }

  private handleAccessSaved() {
    // Set a new 'original' value to keep track of after the value has been
    // saved.
    this.setupValues();
  }

  private permissionIsOwnerOrGlobal(permissionId: string, section: string) {
    return permissionId === 'owner' || section === 'GLOBAL_CAPABILITIES';
  }

  private handleEditingChanged(editingOld: boolean) {
    // Ignore when editing gets set initially.
    if (!editingOld) {
      return;
    }
    if (!this.permission || !this.rules) {
      return;
    }

    // Restore original values if no longer editing.
    if (!this.editing) {
      this.deleted = false;
      delete this.permission.value.deleted;
      this.groupFilter = '';
      this.rules = this.rules.filter(rule => !rule.value!.added);
      this.handleRulesChanged();
      for (const key of Object.keys(this.permission.value.rules)) {
        if (this.permission.value.rules[key].added) {
          delete this.permission.value.rules[key];
        }
      }

      // Restore exclusive bit to original.
      this.permission.value.exclusive = this.originalExclusiveValue;
      fire(this, 'permission-changed', {value: this.permission});
      this.requestUpdate();
    }
  }

  private handleAddedRuleRemoved(index: number) {
    if (!this.rules) {
      return;
    }
    this.rules = this.rules
      .slice(0, index)
      .concat(this.rules.slice(index + 1, this.rules.length));
    this.handleRulesChanged();
  }

  handleValueChange(e: Event) {
    if (!this.permission) {
      return;
    }
    this.permission.value.modified = true;
    this.permission.value.exclusive = (e.target as HTMLInputElement).checked;
    // Allows overall access page to know a change has been made.
    fire(this, 'access-modified', {});
  }

  handleRemovePermission() {
    if (!this.permission) {
      return;
    }
    if (this.permission.value.added) {
      fire(this, 'added-permission-removed', {});
    }
    this.deleted = true;
    this.permission.value.deleted = true;
    fire(this, 'access-modified', {});
  }

  private handleRulesChanged() {
    if (!this.rules) {
      return;
    }
    // Update the groups to exclude in the autocomplete.
    this.groupsWithRules = this.computeGroupsWithRules(this.rules);
  }

  sortPermission(permission?: PermissionArrayItem<EditablePermissionInfo>) {
    this.rules = toSortedPermissionsArray(permission?.value.rules);
    this.handleRulesChanged();
  }

  computeSectionClass(editing: boolean, deleted: boolean) {
    const classList = [];
    if (editing) {
      classList.push('editing');
    }
    if (deleted) {
      classList.push('deleted');
    }
    return classList.join(' ');
  }

  handleUndoRemove() {
    if (!this.permission) {
      return;
    }
    this.deleted = false;
    delete this.permission.value.deleted;
  }

  computeLabel(): ComputedLabel | undefined {
    const {permission, labels} = this;
    if (
      !labels ||
      !permission ||
      !permission.value ||
      !permission.value.label
    ) {
      return;
    }

    const labelName = permission.value.label;

    // It is possible to have a label name that is not included in the
    // 'labels' object. In this case, treat it like anything else.
    if (!labels[labelName]) {
      return;
    }
    return {
      name: labelName,
      values: this.computeLabelValues(labels[labelName].values),
    };
  }

  computeLabelValues(values: LabelTypeInfoValues): ComputedLabelValue[] {
    const valuesArr: ComputedLabelValue[] = [];
    const keys = Object.keys(values).sort((a, b) => Number(a) - Number(b));

    for (const key of keys) {
      let text = values[key];
      if (!text) {
        text = '';
      }
      // The value from the server being used to choose which item is
      // selected is in integer form, so this must be converted.
      valuesArr.push({value: Number(key), text});
    }
    return valuesArr;
  }

  computeGroupsWithRules(
    rules: PermissionArray<EditablePermissionRuleInfo | undefined>
  ): GroupsWithRulesMap {
    const groups: GroupsWithRulesMap = {};
    for (const rule of rules) {
      groups[rule.id] = true;
    }
    return groups;
  }

  computeGroupName(
    groups: EditableRepoAccessGroups | undefined,
    groupId: GitRef
  ) {
    return groups && groups[groupId] && groups[groupId].name
      ? groups[groupId].name
      : `${groupId} (Group is unavailable)`;
  }

  getGroupSuggestions(): Promise<AutocompleteSuggestion[]> {
    return this.restApiService
      .getSuggestedGroups(
        this.groupFilter || '',
        this.repo,
        MAX_AUTOCOMPLETE_RESULTS,
        throwingErrorCallback
      )
      .then(response => {
        const groups: GroupSuggestion[] = [];
        for (const [name, value] of Object.entries(response ?? {})) {
          groups.push({name, value});
        }
        // Does not return groups in which we already have rules for.
        return groups
          .filter(
            group =>
              this.groupsWithRules && !this.groupsWithRules[group.value.id]
          )
          .map((group: GroupSuggestion) => {
            const autocompleteSuggestion: AutocompleteSuggestion = {
              name: group.name,
              value: group.value.id,
            };
            return autocompleteSuggestion;
          });
      });
  }

  /**
   * Handles adding a skeleton item to the dom-repeat.
   * gr-rule-editor handles setting the default values.
   */
  async handleAddRuleItem(e: AutocompleteCommitEvent) {
    if (!this.permission || !this.rules) {
      return;
    }

    // The group id is encoded, but have to decode in order for the access
    // API to work as expected.
    const groupId = decodeURIComponent(e.detail.value).replace(/\+/g, ' ');
    // We cannot use "this.set(...)" here, because groupId may contain dots,
    // and dots in property path names are totally unsupported by Polymer.
    // Apparently Polymer picks up this change anyway, otherwise we should
    // have looked at using MutableData:
    // https://polymer-library.polymer-project.org/2.0/docs/devguide/data-system#mutable-data
    // Actual value assigned below, after the flush
    this.permission.value.rules[groupId] = {} as EditablePermissionRuleInfo;

    // Purposely don't recompute sorted array so that the newly added rule
    // is the last item of the array.
    this.rules.push({
      id: groupId as GitRef,
      value: undefined,
    });
    // Wait for new rule to get value populated via gr-rule-editor, and then
    // add to permission values as well, so that the change gets propagated
    // back to the section. Since the rule is inside a dom-repeat, a flush
    // is needed.
    this.requestUpdate();
    await this.updateComplete;

    // Add the new group name to the groups object so the name renders
    // correctly.
    if (this.groups && !this.groups[groupId]) {
      this.groups[groupId] = {name: this.groupAutocomplete.text};
    }

    // Clear the text of the auto-complete box, so that the user can add the
    // next group.
    this.groupAutocomplete.text = '';

    const value = this.rules[this.rules.length - 1].value;
    value!.added = true;
    this.permission.value.rules[groupId] = value!;
    fire(this, 'access-modified', {});
    this.requestUpdate();
  }

  computeHasRange(name?: string) {
    if (!name) {
      return false;
    }

    return RANGE_NAMES.includes(name.toUpperCase());
  }

  private computeExclusiveLabel(permission?: EditablePermissionInfo) {
    return permission?.exclusive ? 'Exclusive' : 'Not Exclusive';
  }

  /**
   * Work around a issue on iOS when clicking turns into double tap
   */
  private onTapExclusiveToggle(e: Event) {
    e.preventDefault();
  }

  // TODO: Do not use generic `CustomEvent`.
  // There is something fishy going on here though.
  // `e.detail.value` is of type `Rule`, but `splice()` expects a `number`.
  // Did not look closer, but this seems to be broken. Should `e.detail.value`
  // be replaced by `1` maybe??
  private handleRuleChanged(e: CustomEvent, index: number) {
    this.rules!.splice(index, e.detail.value);
    this.handleRulesChanged();
    this.requestUpdate();
  }
}

declare global {
  interface HTMLElementEventMap {
    /** Fired when a permission that was previously added was removed. */
    'added-permission-removed': CustomEvent<{}>;
    'permission-changed': ValueChangedEvent<
      PermissionArrayItem<EditablePermissionInfo>
    >;
  }
  interface HTMLElementTagNameMap {
    'gr-permission': GrPermission;
  }
}
