/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../gr-access-section/gr-access-section';
import {singleDecodeURL} from '../../../utils/url-util';
import {navigationToken} from '../../core/gr-navigation/gr-navigation';
import {toSortedPermissionsArray} from '../../../utils/access-util';
import {
  CapabilityInfoMap,
  GitRef,
  LabelNameToLabelTypeInfoMap,
  ProjectAccessInput,
  ProjectInfo,
  RepoAccessGroups,
  RepoName,
  UrlEncodedRepoName,
} from '../../../types/common';
import {GrButton} from '../../shared/gr-button/gr-button';
import {GrAccessSection} from '../gr-access-section/gr-access-section';
import {AutocompleteQuery} from '../../shared/gr-autocomplete/gr-autocomplete';
import {AutocompleteSuggestion} from '../../../utils/autocomplete-util';
import {
  EditableLocalAccessSectionInfo,
  PermissionAccessSection,
  PrimitiveValue,
  PropertyTreeNode,
} from './gr-repo-access-interfaces';
import {fireAlert, firePageError} from '../../../utils/event-util';
import {getAppContext} from '../../../services/app-context';
import {WebLinkInfo} from '../../../types/diff';
import {fontStyles} from '../../../styles/gr-font-styles';
import {menuPageStyles} from '../../../styles/gr-menu-page-styles';
import {subpageStyles} from '../../../styles/gr-subpage-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {css, html, LitElement, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {assertIsDefined} from '../../../utils/common-util';
import {
  AutocompleteCommitEvent,
  ValueChangedEvent,
} from '../../../types/events';
import {resolve} from '../../../models/dependency';
import {createChangeUrl} from '../../../models/views/change';
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {createRepoUrl, RepoDetailView} from '../../../models/views/repo';
import '../../shared/gr-weblink/gr-weblink';

const NOTHING_TO_SAVE = 'No changes to save.';

const MAX_AUTOCOMPLETE_RESULTS = 50;

declare global {
  interface HTMLElementTagNameMap {
    'gr-repo-access': GrRepoAccess;
  }
}

/**
 * Fired when save is a no-op
 *
 * @event show-alert
 */
@customElement('gr-repo-access')
export class GrRepoAccess extends LitElement {
  @query('gr-access-section:last-of-type') accessSection?: GrAccessSection;

  @property({type: String})
  repo?: RepoName;

  // private but used in test
  @state() canUpload?: boolean = false; // restAPI can return undefined

  @state() disableSaveWithoutReview = true;

  // private but used in test
  @state() inheritFromFilter?: RepoName;

  // private but used in test
  @state() ownerOf?: GitRef[];

  // private but used in test
  @state() capabilities?: CapabilityInfoMap;

  // private but used in test
  @state() groups?: RepoAccessGroups;

  // private but used in test
  @state() inheritsFrom?: ProjectInfo;

  // private but used in test
  @state() labels?: LabelNameToLabelTypeInfoMap;

  // private but used in test
  @state() local?: EditableLocalAccessSectionInfo;

  // private but used in test
  @state() editing = false;

  // private but used in test
  @state() modified = false;

  // private but used in test
  @state() sections?: PermissionAccessSection[];

  @state() private weblinks?: WebLinkInfo[];

  // private but used in test
  @state() loading = true;

  // private but used in the tests
  originalInheritsFrom?: ProjectInfo;

  private readonly query: AutocompleteQuery;

  private readonly restApiService = getAppContext().restApiService;

  private readonly getNavigation = resolve(this, navigationToken);

  constructor() {
    super();
    this.query = () => this.getInheritFromSuggestions();
    this.addEventListener('access-modified', () =>
      this._handleAccessModified()
    );
  }

  static override get styles() {
    return [
      fontStyles,
      menuPageStyles,
      subpageStyles,
      sharedStyles,
      css`
        gr-button,
        #inheritsFrom,
        #editInheritFromInput,
        .editing #inheritFromName,
        .weblinks,
        .editing .invisible {
          display: none;
        }
        #inheritsFrom.show {
          display: flex;
          min-height: 2em;
          align-items: center;
        }
        gr-weblink {
          margin-right: var(--spacing-xs);
        }
        gr-access-section {
          margin-top: var(--spacing-l);
        }
        .weblinks.show,
        .referenceContainer {
          display: block;
          align-content: center;
        }
        .rightsText {
          margin-right: var(--spacing-s);
        }

        .editing gr-button,
        .admin #editBtn {
          display: inline-block;
          margin: var(--spacing-l);
        }
        .editing #editInheritFromInput {
          display: inline-block;
        }

        .topLevelButtons {
          display: flex;
        }
      `,
    ];
  }

  override render() {
    return html`
      <div class="main ${this.computeMainClass()}">
        <div id="loading" class=${this.loading ? 'loading' : ''}>
          Loading...
        </div>
        <div id="loadedContent" class=${this.loading ? 'loading' : ''}>
          <h3
            id="inheritsFrom"
            class="heading-3 ${this.editing || this.inheritsFrom?.id?.length
              ? 'show'
              : ''}"
          >
            <span class="rightsText">Rights Inherit From</span>
            <a
              id="inheritFromName"
              href=${this.computeParentHref()}
              rel="noopener"
            >
              ${this.inheritsFrom?.name}</a
            >
            <gr-autocomplete
              id="editInheritFromInput"
              .text=${this.inheritFromFilter ?? ''}
              .query=${this.query}
              .showBlueFocusBorder=${true}
              @commit=${(e: AutocompleteCommitEvent) => {
                this.handleUpdateInheritFrom(e);
              }}
              @text-changed=${(e: ValueChangedEvent) => {
                this.handleEditInheritFromTextChanged(e);
                this.handleUpdateInheritFrom(e);
              }}
            ></gr-autocomplete>
          </h3>
          <div class="topLevelButtons">
            <div class="weblinks ${this.weblinks?.length ? 'show' : ''}">
              History:
              ${this.weblinks?.map(
                info => html`<gr-weblink .info=${info}></gr-weblink>`
              )}
            </div>
            <div>
              <gr-button
                id="editBtn"
                @click=${() => {
                  this.handleEdit();
                }}
                >${this.editing ? 'Cancel' : 'Edit'}</gr-button
              >
              <gr-button
                id="saveBtn"
                class=${this.ownerOf && this.ownerOf.length === 0
                  ? 'invisible'
                  : ''}
                primary
                ?disabled=${!this.modified || this.disableSaveWithoutReview}
                @click=${this.handleSave}
                >Save</gr-button
              >
              <gr-button
                id="saveReviewBtn"
                class=${!this.canUpload ? 'invisible' : ''}
                primary
                ?disabled=${!this.modified}
                @click=${this.handleSaveForReview}
                >Save For Review</gr-button
              >
            </div>
          </div>
          ${this.sections?.map((section, index) =>
            this.renderPermissionSections(section, index)
          )}
          <div class="referenceContainer">
            <gr-button
              id="addReferenceBtn"
              @click=${() => this.handleCreateSection()}
              >Add Reference</gr-button
            >
          </div>
        </div>
      </div>
    `;
  }

  private renderPermissionSections(
    section: PermissionAccessSection,
    index: number
  ) {
    return html`
      <gr-access-section
        .capabilities=${this.capabilities}
        .section=${section}
        .labels=${this.labels}
        .canUpload=${this.canUpload}
        .editing=${this.editing}
        .ownerOf=${this.ownerOf}
        .groups=${this.groups}
        .repo=${this.repo}
        @added-section-removed=${() => {
          this.handleAddedSectionRemoved(index);
        }}
        @section-changed=${(e: ValueChangedEvent<PermissionAccessSection>) => {
          this.handleAccessSectionChanged(e, index);
        }}
      ></gr-access-section>
    `;
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('repo')) {
      this._repoChanged(this.repo);
    }

    if (changedProperties.has('editing')) {
      this.handleEditingChanged(changedProperties.get('editing') as boolean);
      this.requestUpdate();
    }
  }

  _handleAccessModified() {
    this.modified = true;
  }

  _repoChanged(repo?: RepoName) {
    this.loading = true;

    if (!repo) {
      return Promise.resolve();
    }

    return this.reload(repo);
  }

  private reload(repo: RepoName) {
    const errFn = (response?: Response | null) => {
      firePageError(response);
    };

    this.editing = false;

    // Always reset sections when a repo changes.
    this.sections = [];
    const sectionsPromises = this.restApiService
      .getRepoAccessRights(repo, errFn)
      .then(res => {
        if (!res) {
          return Promise.resolve(undefined);
        }

        // Keep a copy of the original inherit from values separate from
        // the ones data bound to gr-autocomplete, so the original value
        // can be restored if the user cancels.
        if (res.inherits_from) {
          this.inheritsFrom = {...res.inherits_from};
          this.originalInheritsFrom = {...res.inherits_from};
        } else {
          this.inheritsFrom = undefined;
          this.originalInheritsFrom = undefined;
        }
        // Initialize the filter value so when the user clicks edit, the
        // current value appears. If there is no parent repo, it is
        // initialized as an empty string.
        this.inheritFromFilter = res.inherits_from
          ? res.inherits_from.name
          : ('' as RepoName);
        // 'as EditableLocalAccessSectionInfo' is required because res.local
        // type doesn't have index signature
        this.local = res.local as EditableLocalAccessSectionInfo;
        this.groups = res.groups;
        this.weblinks = res.config_web_links || [];
        this.canUpload = res.can_upload;
        this.disableSaveWithoutReview = !!res.require_change_for_config_update;
        this.ownerOf = res.owner_of || [];
        return toSortedPermissionsArray(this.local);
      });

    const capabilitiesPromises = this.restApiService
      .getCapabilities(errFn)
      .then(res => {
        if (!res) {
          return Promise.resolve(undefined);
        }

        return res;
      });

    const labelsPromises = this.restApiService
      .getRepo(repo, errFn)
      .then(res => {
        if (!res) {
          return Promise.resolve(undefined);
        }

        return res.labels;
      });

    return Promise.all([
      sectionsPromises,
      capabilitiesPromises,
      labelsPromises,
    ]).then(([sections, capabilities, labels]) => {
      this.capabilities = capabilities;
      this.labels = labels;
      this.sections = sections;
      this.loading = false;
    });
  }

  // private but used in test
  handleUpdateInheritFrom(e: AutocompleteCommitEvent) {
    this.inheritsFrom = {
      ...(this.inheritsFrom ?? {}),
      id: e.detail.value as UrlEncodedRepoName,
      name: this.inheritFromFilter,
    };
    this._handleAccessModified();
  }

  private getInheritFromSuggestions(): Promise<AutocompleteSuggestion[]> {
    return this.restApiService
      .getRepos(
        this.inheritFromFilter,
        MAX_AUTOCOMPLETE_RESULTS,
        /* offset=*/ undefined,
        throwingErrorCallback
      )
      .then(response => {
        const repos: AutocompleteSuggestion[] = [];
        if (!response) {
          return repos;
        }
        for (const item of response) {
          repos.push({
            name: item.name,
            value: item.id,
          });
        }
        return repos;
      });
  }

  private handleEdit() {
    this.editing = !this.editing;
  }

  // private but used in tests
  handleAddedSectionRemoved(index: number) {
    if (!this.sections) return;
    assertIsDefined(this.local, 'local');
    delete this.local[this.sections[index].id];
    this.sections = this.sections
      .slice(0, index)
      .concat(this.sections.slice(index + 1, this.sections.length));
  }

  private handleEditingChanged(editingOld: boolean) {
    // Ignore when editing gets set initially.
    if (!editingOld || this.editing) {
      return;
    }
    // Remove any unsaved but added refs.
    if (this.sections) {
      this.sections = this.sections.filter(p => !p.value.added);
    }
    // Restore inheritFrom.
    if (this.inheritsFrom) {
      this.inheritsFrom = this.originalInheritsFrom
        ? {...this.originalInheritsFrom}
        : undefined;
      this.inheritFromFilter = this.originalInheritsFrom?.name;
    }
    if (!this.local) {
      return;
    }
    for (const key of Object.keys(this.local)) {
      if (this.local[key].added) {
        delete this.local[key];
      }
    }
  }

  private updateRemoveObj(
    addRemoveObj: {remove: PropertyTreeNode},
    path: string[]
  ) {
    let curPos: PropertyTreeNode = addRemoveObj.remove;
    for (const item of path) {
      if (!curPos[item]) {
        if (item === path[path.length - 1]) {
          if (path[path.length - 2] === 'permissions') {
            curPos[item] = {rules: {}};
          } else if (path.length === 1) {
            curPos[item] = {permissions: {}};
          } else {
            curPos[item] = {};
          }
        } else {
          curPos[item] = {};
        }
      }
      // The last item can be a PrimitiveValue, but we don't use it
      // All intermediate items are PropertyTreeNode
      // TODO(TS): rewrite this loop and process the last item explicitly
      curPos = curPos[item] as PropertyTreeNode;
    }
    return addRemoveObj;
  }

  private updateAddObj(
    addRemoveObj: {add: PropertyTreeNode},
    path: string[],
    value: PropertyTreeNode | PrimitiveValue
  ) {
    let curPos: PropertyTreeNode = addRemoveObj.add;
    for (const item of path) {
      if (!curPos[item]) {
        if (item === path[path.length - 1]) {
          curPos[item] = value;
        } else {
          curPos[item] = {};
        }
      }
      // The last item can be a PrimitiveValue, but we don't use it
      // All intermediate items are PropertyTreeNode
      // TODO(TS): rewrite this loop and process the last item explicitly
      curPos = curPos[item] as PropertyTreeNode;
    }
    return addRemoveObj;
  }

  /**
   * Used to recursively remove any objects with a 'deleted' bit.
   *
   * private but used in test
   */
  recursivelyRemoveDeleted(obj?: PropertyTreeNode) {
    if (!obj) return;
    for (const k of Object.keys(obj)) {
      const node = obj[k];
      if (typeof node === 'object') {
        if (node.deleted) {
          delete obj[k];
          return;
        }
        this.recursivelyRemoveDeleted(node);
      }
    }
  }

  // private but used in test
  recursivelyUpdateAddRemoveObj(
    obj: PropertyTreeNode | undefined,
    addRemoveObj: {
      add: PropertyTreeNode;
      remove: PropertyTreeNode;
    },
    path: string[] = []
  ) {
    if (!obj) return;
    for (const k of Object.keys(obj)) {
      const node = obj[k];
      if (typeof node === 'object') {
        const updatedId = node.updatedId;
        const ref = updatedId ? updatedId : k;
        if (node.deleted) {
          this.updateRemoveObj(addRemoveObj, path.concat(k));
          continue;
        } else if (node.modified) {
          this.updateRemoveObj(addRemoveObj, path.concat(k));
          this.updateAddObj(addRemoveObj, path.concat(ref), node);
          /* Special case for ref changes because they need to be added and
          removed in a different way. The new ref needs to include all
          changes but also the initial state. To do this, instead of
          continuing with the same recursion, just remove anything that is
          deleted in the current state. */
          if (updatedId && updatedId !== k) {
            this.recursivelyRemoveDeleted(
              addRemoveObj.add[updatedId] as PropertyTreeNode
            );
          }
          continue;
        } else if (node.added) {
          this.updateAddObj(addRemoveObj, path.concat(ref), node);
          /**
           * As add / delete both can happen in the new section,
           * so here to make sure it will remove the deleted ones.
           *
           * @see Issue 11339
           */
          this.recursivelyRemoveDeleted(
            addRemoveObj.add[k] as PropertyTreeNode
          );
          continue;
        }
        this.recursivelyUpdateAddRemoveObj(node, addRemoveObj, path.concat(k));
      }
    }
  }

  /**
   * Returns an object formatted for saving or submitting access changes for
   * review
   *
   * private but used in test
   */
  computeAddAndRemove() {
    const addRemoveObj: {
      add: PropertyTreeNode;
      remove: PropertyTreeNode;
      parent?: string | null;
    } = {
      add: {},
      remove: {},
    };

    const originalInheritsFromId = this.originalInheritsFrom
      ? singleDecodeURL(this.originalInheritsFrom.id)
      : undefined;
    const inheritsFromId = this.inheritsFrom
      ? singleDecodeURL(this.inheritsFrom.id)
      : undefined;

    const inheritFromChanged =
      // Inherit from changed
      (originalInheritsFromId && originalInheritsFromId !== inheritsFromId) ||
      // Inherit from added (did not have one initially);
      (!originalInheritsFromId && inheritsFromId);

    if (!this.local) {
      return addRemoveObj;
    }

    this.recursivelyUpdateAddRemoveObj(
      this.local as unknown as PropertyTreeNode,
      addRemoveObj
    );

    if (inheritFromChanged) {
      addRemoveObj.parent = inheritsFromId;
    }
    return addRemoveObj;
  }

  private handleCreateSection() {
    if (!this.local) return;
    let newRef = 'refs/for/*';
    // Avoid using an already used key for the placeholder, since it
    // immediately gets added to an object.
    while (this.local[newRef]) {
      newRef = `${newRef}*`;
    }
    const section = {permissions: {}, added: true};
    this.sections!.push({id: newRef as GitRef, value: section});
    this.local[newRef] = section;
    this.requestUpdate();
    assertIsDefined(this.accessSection, 'accessSection');
    // Template already instantiated at this point
    this.accessSection.editReference();
  }

  private getObjforSave(): ProjectAccessInput | undefined {
    const addRemoveObj = this.computeAddAndRemove();
    // If there are no changes, don't actually save.
    if (
      !Object.keys(addRemoveObj.add).length &&
      !Object.keys(addRemoveObj.remove).length &&
      !addRemoveObj.parent
    ) {
      fireAlert(this, NOTHING_TO_SAVE);
      return;
    }
    const obj: ProjectAccessInput = {
      add: addRemoveObj.add,
      remove: addRemoveObj.remove,
    } as unknown as ProjectAccessInput;
    if (addRemoveObj.parent) {
      obj.parent = addRemoveObj.parent;
    }
    return obj;
  }

  // private but used in test
  handleSave(e: Event) {
    const obj = this.getObjforSave();
    if (!obj) {
      return;
    }
    const button = e && (e.target as GrButton);
    if (button) {
      button.loading = true;
    }
    const repo = this.repo;
    if (!repo) {
      return Promise.resolve();
    }
    return this.restApiService
      .setRepoAccessRights(repo, obj)
      .then(() => {
        this.reload(repo);
      })
      .finally(() => {
        this.modified = false;
        if (button) {
          button.loading = false;
        }
      });
  }

  // private but used in test
  handleSaveForReview(e: Event) {
    const obj = this.getObjforSave();
    if (!obj) {
      return;
    }
    const button = e && (e.target as GrButton);
    if (button) {
      button.loading = true;
    }
    if (!this.repo) {
      return;
    }
    return this.restApiService
      .setRepoAccessRightsForReview(this.repo, obj)
      .then(change => {
        // Don't navigate on server error.
        if (change) {
          this.getNavigation().setUrl(createChangeUrl({change}));
        }
      })
      .finally(() => {
        this.modified = false;
        if (button) {
          button.loading = false;
        }
      });
  }

  // private but used in test
  computeMainClass() {
    const classList = [];
    if ((this.ownerOf && this.ownerOf.length > 0) || this.canUpload) {
      classList.push('admin');
    }
    if (this.editing) {
      classList.push('editing');
    }
    return classList.join(' ');
  }

  computeParentHref() {
    if (!this.inheritsFrom?.name) return '';
    return createRepoUrl({
      repo: this.inheritsFrom.name,
      detail: RepoDetailView.ACCESS,
    });
  }

  private handleEditInheritFromTextChanged(e: ValueChangedEvent) {
    this.inheritFromFilter = e.detail.value as RepoName;
  }

  private handleAccessSectionChanged(
    e: ValueChangedEvent<PermissionAccessSection>,
    index: number
  ) {
    this.sections![index] = e.detail.value;
    this.requestUpdate();
  }
}
