/**
 * @license
 * Copyright 2017 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../gr-access-section/gr-access-section';
import {encodeURL, getBaseUrl, 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 {ValueChangedEvent} from '../../../types/events';
import {ifDefined} from 'lit/directives/if-defined.js';
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';

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: ValueChangedEvent) => {
                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=${ifDefined(webLink.target)}
      >
        ${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: ValueChangedEvent) {
    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 `${getBaseUrl()}/admin/repos/${encodeURL(
      this.inheritsFrom.name,
      true
    )},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();
  }
}
