/**
 * @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';

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

  // 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;
        }
        .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(webLink => this.renderWebLinks(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}
              @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 renderWebLinks(webLink: WebLinkInfo) {
    return html`
      <a class="weblink" href=${webLink.url} rel="noopener" target="_blank">
        ${webLink.name}
      </a>
    `;
  }

  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.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 => {
        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();
  }
}
