/**
 * @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 {
  RepoName,
  ProjectInfo,
  CapabilityInfoMap,
  LabelNameToLabelTypeInfoMap,
  ProjectAccessInput,
  GitRef,
  UrlEncodedRepoName,
  RepoAccessGroups,
} from '../../../types/common';
import {GrButton} from '../../shared/gr-button/gr-button';
import {GrAccessSection} from '../gr-access-section/gr-access-section';
import {
  AutocompleteQuery,
  AutocompleteSuggestion,
} from '../../shared/gr-autocomplete/gr-autocomplete';
import {
  EditableLocalAccessSectionInfo,
  PermissionAccessSection,
  PropertyTreeNode,
  PrimitiveValue,
} from './gr-repo-access-interfaces';
import {firePageError, fireAlert} 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 {LitElement, PropertyValues, css, html} 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;
        }
        .rightsText {
          margin-right: var(--spacing-s);
        }

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

  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}
              @commit=${(e: AutocompleteCommitEvent) => {
                this.handleUpdateInheritFrom(e);
              }}
              @bind-value-changed=${(e: ValueChangedEvent) => {
                this.handleUpdateInheritFrom(e);
              }}
              @text-changed=${(e: ValueChangedEvent) => {
                this.handleEditInheritFromTextChanged(e);
              }}
            ></gr-autocomplete>
          </h3>
          <div class="weblinks ${this.weblinks?.length ? 'show' : ''}">
            History:
            ${this.weblinks?.map(
              info => html`<gr-weblink .info=${info}></gr-weblink>`
            )}
          </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>
            <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>
      </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();
  }
}
