/**
 * @license
 * Copyright 2015 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../gr-change-list/gr-change-list';
import '../gr-repo-header/gr-repo-header';
import '../gr-user-header/gr-user-header';
import {page} from '../../../utils/page-wrapper-utils';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {
  AccountDetailInfo,
  AccountId,
  ChangeInfo,
  EmailAddress,
  PreferencesInput,
  RepoName,
} from '../../../types/common';
import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star';
import {fireAlert, fireEvent, fireTitleChange} from '../../../utils/event-util';
import {getAppContext} from '../../../services/app-context';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, PropertyValues, html, css, nothing} from 'lit';
import {customElement, state, query} from 'lit/decorators.js';
import {ValueChangedEvent} from '../../../types/events';
import {
  createSearchUrl,
  searchViewModelToken,
  SearchViewState,
} from '../../../models/views/search';
import {resolve} from '../../../models/dependency';
import {subscribe} from '../../lit/subscription-controller';

const LOOKUP_QUERY_PATTERNS: RegExp[] = [
  /^\s*i?[0-9a-f]{7,40}\s*$/i, // CHANGE_ID
  /^\s*[1-9][0-9]*\s*$/g, // CHANGE_NUM
  /[0-9a-f]{40}/, // COMMIT
];

const USER_QUERY_PATTERN = /^owner:\s?("[^"]+"|[^ ]+)$/;

const REPO_QUERY_PATTERN =
  /^project:\s?("[^"]+"|[^ ]+)(\sstatus\s?:(open|"open"))?$/;

const LIMIT_OPERATOR_PATTERN = /\blimit:(\d+)/i;

@customElement('gr-change-list-view')
export class GrChangeListView extends LitElement {
  /**
   * Fired when the title of the page should change.
   *
   * @event title-change
   */

  @query('#prevArrow') protected prevArrow?: HTMLAnchorElement;

  @query('#nextArrow') protected nextArrow?: HTMLAnchorElement;

  private _viewState?: SearchViewState;

  @state()
  get viewState() {
    return this._viewState;
  }

  set viewState(viewState: SearchViewState | undefined) {
    if (this._viewState === viewState) return;
    const oldViewState = this._viewState;
    this._viewState = viewState;
    this.viewStateChanged();
    this.requestUpdate('viewState', oldViewState);
  }

  // private but used in test
  @state() account?: AccountDetailInfo;

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

  // private but used in test
  @state() preferences?: PreferencesInput;

  // private but used in test
  @state() changesPerPage?: number;

  // private but used in test
  @state() query = '';

  // private but used in test
  @state() offset?: number;

  // private but used in test
  @state() changes?: ChangeInfo[];

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

  // private but used in test
  @state() userId: AccountId | EmailAddress | null = null;

  // private but used in test
  @state() repo: RepoName | null = null;

  @state() selectedIndex = 0;

  private readonly restApiService = getAppContext().restApiService;

  private reporting = getAppContext().reportingService;

  private userModel = getAppContext().userModel;

  private readonly getViewModel = resolve(this, searchViewModelToken);

  constructor() {
    super();
    this.addEventListener('next-page', () => this.handleNextPage());
    this.addEventListener('previous-page', () => this.handlePreviousPage());
    this.addEventListener('reload', () => this.reload());
    subscribe(
      this,
      () => this.getViewModel().state$,
      x => (this.viewState = x)
    );
    subscribe(
      this,
      () => this.userModel.account$,
      x => (this.account = x)
    );
    subscribe(
      this,
      () => this.userModel.loggedIn$,
      x => (this.loggedIn = x)
    );
    subscribe(
      this,
      () => this.userModel.preferences$,
      x => {
        this.preferences = x;
        if (this.changesPerPage !== x.changes_per_page) {
          this.changesPerPage = x.changes_per_page;
          this.viewStateChanged();
        }
      }
    );
  }

  static override get styles() {
    return [
      sharedStyles,
      css`
        :host {
          display: block;
        }
        .loading {
          color: var(--deemphasized-text-color);
          padding: var(--spacing-l);
        }
        gr-change-list {
          width: 100%;
        }
        gr-user-header,
        gr-repo-header {
          border-bottom: 1px solid var(--border-color);
        }
        nav {
          align-items: center;
          display: flex;
          height: 3rem;
          justify-content: flex-end;
          margin-right: 20px;
          color: var(--deemphasized-text-color);
        }
        gr-icon {
          font-size: 1.85rem;
          margin-left: 16px;
        }
        .hide {
          display: none;
        }
        @media only screen and (max-width: 50em) {
          .loading,
          .error {
            padding: 0 var(--spacing-l);
          }
        }
      `,
    ];
  }

  override render() {
    // In case of an internal reload we want the ChangeList section components
    // to remain in the DOM so that the Bulk Actions Model associated with them
    // is not recreated after the reload resulting in user selections being lost
    return html`
      <div class="loading" ?hidden=${!this.loading}>Loading...</div>
      <div ?hidden=${this.loading}>
        ${this.renderRepoHeader()} ${this.renderUserHeader()}
        <gr-change-list
          .account=${this.account}
          .changes=${this.changes}
          .preferences=${this.preferences}
          .showStar=${this.loggedIn}
          .selectedIndex=${this.selectedIndex}
          @selected-index-changed=${(e: ValueChangedEvent<number>) => {
            this.selectedIndex = e.detail.value;
          }}
          @toggle-star=${(e: CustomEvent<ChangeStarToggleStarDetail>) => {
            this.handleToggleStar(e);
          }}
          .usp=${'search'}
        ></gr-change-list>
        ${this.renderChangeListViewNav()}
      </div>
    `;
  }

  private renderRepoHeader() {
    if (!this.repo) return nothing;

    return html` <gr-repo-header .repo=${this.repo}></gr-repo-header> `;
  }

  private renderUserHeader() {
    if (!this.userId) return nothing;

    return html`
      <gr-user-header
        .userId=${this.userId}
        showDashboardLink
        .loggedIn=${this.loggedIn}
      ></gr-user-header>
    `;
  }

  private renderChangeListViewNav() {
    if (this.loading || !this.changes || !this.changes.length) return nothing;

    return html`
      <nav>
        Page ${this.computePage()} ${this.renderPrevArrow()}
        ${this.renderNextArrow()}
      </nav>
    `;
  }

  private renderPrevArrow() {
    if (this.offset === 0) return nothing;

    return html`
      <a id="prevArrow" href=${this.computeNavLink(-1)}>
        <gr-icon icon="chevron_left" aria-label="Older"></gr-icon>
      </a>
    `;
  }

  private renderNextArrow() {
    const changesCount = this.changes?.length ?? 0;
    if (changesCount === 0) return nothing;
    if (!this.changes?.[changesCount - 1]._more_changes) return nothing;

    return html`
      <a id="nextArrow" href=${this.computeNavLink(1)}>
        <gr-icon icon="chevron_right" aria-label="Newer"></gr-icon>
      </a>
    `;
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('changes')) {
      this.changesChanged();
    }
  }

  reload() {
    if (this.loading) return;
    this.loading = true;
    this.getChanges().then(changes => {
      this.changes = changes || [];
      this.loading = false;
    });
  }

  // private, but visible for testing
  viewStateChanged() {
    if (!this.viewState) return;

    let offset = Number(this.viewState.offset);
    if (isNaN(offset)) offset = 0;
    const query = this.viewState.query ?? '';

    if (this.query !== query) this.selectedIndex = 0;
    this.loading = true;
    this.query = query;
    this.offset = offset;

    // NOTE: This method may be called before attachment. Fire title-change
    // in an async so that attachment to the DOM can take place first.
    setTimeout(() => fireTitleChange(this, this.query));

    return this.getChanges().then(changes => {
      changes = changes || [];
      if (this.query && changes.length === 1) {
        for (const queryPattern of LOOKUP_QUERY_PATTERNS) {
          if (this.query.match(queryPattern)) {
            // "Back"/"Forward" buttons work correctly only with
            // opt_redirect options
            GerritNav.navigateToChange(changes[0], {
              redirect: true,
            });
            return;
          }
        }
      }
      this.changes = changes;
      this.loading = false;
    });
  }

  // private but used in test
  getChanges() {
    return this.restApiService.getChanges(
      this.changesPerPage,
      this.query,
      this.offset
    );
  }

  // private but used in test
  limitFor(query: string, defaultLimit?: number) {
    if (defaultLimit === undefined) return 0;
    const match = query.match(LIMIT_OPERATOR_PATTERN);
    if (!match) {
      return defaultLimit;
    }
    return Number(match[1]);
  }

  // private but used in test
  computeNavLink(direction: number) {
    const offset = this.offset ?? 0;
    const limit = this.limitFor(this.query, this.changesPerPage);
    const newOffset = Math.max(0, offset + limit * direction);
    return createSearchUrl({query: this.query, offset: newOffset});
  }

  // private but used in test
  handleNextPage() {
    if (!this.nextArrow || !this.changesPerPage) return;
    page.show(this.computeNavLink(1));
  }

  // private but used in test
  handlePreviousPage() {
    if (!this.prevArrow || !this.changesPerPage) return;
    page.show(this.computeNavLink(-1));
  }

  private changesChanged() {
    this.userId = null;
    this.repo = null;
    const changes = this.changes;
    if (!changes || !changes.length) {
      return;
    }
    if (USER_QUERY_PATTERN.test(this.query)) {
      const owner = changes[0].owner;
      const userId = owner._account_id ? owner._account_id : owner.email;
      if (userId) {
        this.userId = userId;
        return;
      }
    }
    if (REPO_QUERY_PATTERN.test(this.query)) {
      this.repo = changes[0].project;
    }
  }

  // private but used in test
  computePage() {
    if (this.offset === undefined || this.changesPerPage === undefined) return;
    return this.offset / this.changesPerPage + 1;
  }

  private async handleToggleStar(e: CustomEvent<ChangeStarToggleStarDetail>) {
    if (e.detail.starred) {
      this.reporting.reportInteraction('change-starred-from-change-list');
    }
    const msg = e.detail.starred
      ? 'Starring change...'
      : 'Unstarring change...';
    fireAlert(this, msg);
    await this.restApiService.saveChangeStarred(
      e.detail.change._number,
      e.detail.starred
    );
    fireEvent(this, 'hide-alert');
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-change-list-view': GrChangeListView;
  }
}
