/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import '@polymer/iron-input/iron-input';
import '../../../styles/shared-styles';
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-dialog/gr-dialog';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-confirm-cherrypick-dialog_html';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {appContext} from '../../../services/app-context';
import {
  ChangeInfo,
  BranchInfo,
  RepoName,
  BranchName,
  CommitId,
  ChangeInfoId,
} from '../../../types/common';
import {ReportingService} from '../../../services/gr-reporting/gr-reporting';
import {customElement, property, observe} from '@polymer/decorators';
import {AutocompleteSuggestion} from '../../shared/gr-autocomplete/gr-autocomplete';
import {HttpMethod, ChangeStatus} from '../../../constants/constants';
import {hasOwnProperty} from '../../../utils/common-util';
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';

const SUGGESTIONS_LIMIT = 15;
const CHANGE_SUBJECT_LIMIT = 50;
enum CherryPickType {
  SINGLE_CHANGE = 1,
  TOPIC,
}

// These values are directly displayed in the dialog to show progress of change
enum ProgressStatus {
  RUNNING = 'RUNNING',
  FAILED = 'FAILED',
  NOT_STARTED = 'NOT STARTED',
  SUCCESSFUL = 'SUCCESSFUL',
}

type Statuses = {[changeId: string]: Status};

interface Status {
  status: ProgressStatus;
  msg?: string;
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-confirm-cherrypick-dialog': GrConfirmCherrypickDialog;
  }
}

export interface GrConfirmCherrypickDialog {
  $: {
    branchInput: HTMLElement;
  };
}

@customElement('gr-confirm-cherrypick-dialog')
export class GrConfirmCherrypickDialog extends GestureEventListeners(
  LegacyElementMixin(PolymerElement)
) {
  static get template() {
    return htmlTemplate;
  }

  /**
   * Fired when the confirm button is pressed.
   *
   * @event confirm
   */

  /**
   * Fired when the cancel button is pressed.
   *
   * @event cancel
   */

  @property({type: String})
  branch?: BranchName;

  @property({type: String})
  baseCommit?: string;

  @property({type: String})
  changeStatus?: ChangeStatus;

  @property({type: String})
  commitMessage?: string;

  @property({type: String})
  commitNum?: CommitId;

  @property({type: String})
  message?: string;

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

  @property({type: Array})
  changes: ChangeInfo[] = [];

  @property({type: Object})
  _query: (input: string) => Promise<AutocompleteSuggestion[]>;

  @property({type: Boolean})
  _showCherryPickTopic = false;

  @property({type: Number})
  _changesCount?: number;

  @property({type: Number})
  _cherryPickType = CherryPickType.SINGLE_CHANGE;

  @property({type: Boolean})
  _duplicateProjectChanges = false;

  @property({type: Object})
  // Status of each change that is being cherry picked together
  _statuses: Statuses;

  @property({type: Boolean})
  _invalidBranch = false;

  @property({type: Object})
  reporting: ReportingService;

  private selectedChangeIds = new Set<ChangeInfoId>();

  private restApiService = appContext.restApiService;

  constructor() {
    super();
    this._statuses = {};
    this.reporting = appContext.reportingService;
    this._query = (text: string) => this._getProjectBranchesSuggestions(text);
  }

  updateChanges(changes: ChangeInfo[]) {
    this.changes = changes;
    this._statuses = {};
    const projects: {[projectName: string]: boolean} = {};
    this._duplicateProjectChanges = false;
    changes.forEach(change => {
      this.selectedChangeIds.add(change.id);
      if (projects[change.project]) {
        this._duplicateProjectChanges = true;
      }
      projects[change.project] = true;
    });
    this._changesCount = changes.length;
    this._showCherryPickTopic = changes.length > 1;
  }

  @observe('branch')
  _updateBranch(branch: string) {
    const invalidChars = [',', ' '];
    this._invalidBranch = !!(
      branch && invalidChars.some(c => branch.includes(c))
    );
  }

  _isChangeSelected(changeId: ChangeInfoId) {
    return this.selectedChangeIds.has(changeId);
  }

  _toggleChangeSelected(e: Event) {
    const changeId = ((dom(e) as EventApi).localTarget as HTMLElement).dataset[
      'item'
    ]! as ChangeInfoId;
    if (this.selectedChangeIds.has(changeId))
      this.selectedChangeIds.delete(changeId);
    else this.selectedChangeIds.add(changeId);
  }

  _computeTopicErrorMessage(duplicateProjectChanges: boolean) {
    if (duplicateProjectChanges) {
      return 'Two changes cannot be of the same project';
    }
    return '';
  }

  updateStatus(change: ChangeInfo, status: Status) {
    this._statuses = {...this._statuses, [change.id]: status};
  }

  _computeStatus(change: ChangeInfo, statuses: Statuses) {
    if (!change || !statuses || !statuses[change.id])
      return ProgressStatus.NOT_STARTED;
    return statuses[change.id].status;
  }

  _computeStatusClass(change: ChangeInfo, statuses: Statuses) {
    if (!change || !statuses || !statuses[change.id]) return '';
    return statuses[change.id].status === ProgressStatus.FAILED ? 'error' : '';
  }

  _computeError(change: ChangeInfo, statuses: Statuses) {
    if (!change || !statuses || !statuses[change.id]) return '';
    if (statuses[change.id].status === ProgressStatus.FAILED) {
      return statuses[change.id].msg;
    }
    return '';
  }

  _getChangeId(change: ChangeInfo) {
    return change.change_id.substring(0, 10);
  }

  _getTrimmedChangeSubject(subject: string) {
    if (!subject) return '';
    if (subject.length < CHANGE_SUBJECT_LIMIT) return subject;
    return subject.substring(0, CHANGE_SUBJECT_LIMIT) + '...';
  }

  _computeCancelLabel(statuses: Statuses) {
    const isRunningChange = Object.values(statuses).some(
      v => v.status === ProgressStatus.RUNNING
    );
    return isRunningChange ? 'Close' : 'Cancel';
  }

  _computeDisableCherryPick(
    cherryPickType: CherryPickType,
    duplicateProjectChanges: boolean,
    statuses: Statuses,
    branch?: BranchName
  ) {
    if (!branch) return true;
    const duplicateProject =
      cherryPickType === CherryPickType.TOPIC && duplicateProjectChanges;
    if (duplicateProject) return true;
    if (!statuses) return false;
    const isRunningChange = Object.values(statuses).some(
      v => v.status === ProgressStatus.RUNNING
    );
    return isRunningChange;
  }

  _computeIfSinglecherryPick(cherryPickType: CherryPickType) {
    return cherryPickType === CherryPickType.SINGLE_CHANGE;
  }

  _computeIfCherryPickTopic(cherryPickType: CherryPickType) {
    return cherryPickType === CherryPickType.TOPIC;
  }

  _handlecherryPickSingleChangeClicked() {
    this._cherryPickType = CherryPickType.SINGLE_CHANGE;
  }

  _handlecherryPickTopicClicked() {
    this._cherryPickType = CherryPickType.TOPIC;
  }

  @observe('changeStatus', 'commitNum', 'commitMessage')
  _computeMessage(
    changeStatus?: string,
    commitNum?: number,
    commitMessage?: string
  ) {
    // Polymer 2: check for undefined
    if (
      changeStatus === undefined ||
      commitNum === undefined ||
      commitMessage === undefined
    ) {
      return;
    }

    let newMessage = commitMessage;

    if (changeStatus === 'MERGED') {
      newMessage += '(cherry picked from commit ' + commitNum.toString() + ')';
    }
    this.message = newMessage;
  }

  _generateRandomCherryPickTopic(change: ChangeInfo) {
    const randomString = Math.random().toString(36).substr(2, 10);
    const message = `cherrypick-${change.topic}-${randomString}`;
    return message;
  }

  _handleCherryPickFailed(change: ChangeInfo, response?: Response | null) {
    if (!response) return;
    response.text().then((errText: string) => {
      this.updateStatus(change, {status: ProgressStatus.FAILED, msg: errText});
    });
  }

  _handleCherryPickTopic() {
    const changes = this.changes.filter(change =>
      this.selectedChangeIds.has(change.id)
    );
    if (!changes.length) {
      const errorSpan = this.shadowRoot?.querySelector('.error-message');
      errorSpan!.innerHTML = 'No change selected';
      return;
    }
    const topic = this._generateRandomCherryPickTopic(changes[0]);
    changes.forEach(change => {
      this.updateStatus(change, {status: ProgressStatus.RUNNING});
      const payload = {
        destination: this.branch,
        base: null,
        topic,
        allow_conflicts: true,
        allow_empty: true,
      };
      const handleError = (response?: Response | null) => {
        this._handleCherryPickFailed(change, response);
      };
      // revisions and current_revision must exist hence casting
      const patchNum = change.revisions![change.current_revision!]._number;
      this.restApiService
        .executeChangeAction(
          change._number,
          HttpMethod.POST,
          '/cherrypick',
          patchNum,
          payload,
          handleError
        )
        .then(() => {
          this.updateStatus(change, {status: ProgressStatus.SUCCESSFUL});
          const failedOrPending = Object.values(this._statuses).find(
            v => v.status !== ProgressStatus.SUCCESSFUL
          );
          if (!failedOrPending) {
            /* This needs some more work, as the new topic may not always be
          created, instead we may end up creating a new patchset */
            GerritNav.navigateToSearchQuery(`topic: "${topic}"`);
          }
        });
    });
  }

  _handleConfirmTap(e: Event) {
    e.preventDefault();
    e.stopPropagation();
    if (this._cherryPickType === CherryPickType.TOPIC) {
      this.reporting.reportInteraction('cherry-pick-topic-clicked', {});
      this._handleCherryPickTopic();
      return;
    }
    // Cherry pick single change
    this.dispatchEvent(
      new CustomEvent('confirm', {
        composed: true,
        bubbles: false,
      })
    );
  }

  _handleCancelTap(e: Event) {
    e.preventDefault();
    e.stopPropagation();
    this.dispatchEvent(
      new CustomEvent('cancel', {
        composed: true,
        bubbles: false,
      })
    );
  }

  resetFocus() {
    this.$.branchInput.focus();
  }

  _getProjectBranchesSuggestions(
    input: string
  ): Promise<AutocompleteSuggestion[]> {
    if (!this.project) {
      this.reporting.error(new Error('no project specified'));
      return Promise.resolve([]);
    }
    if (input.startsWith('refs/heads/')) {
      input = input.substring('refs/heads/'.length);
    }
    return this.restApiService
      .getRepoBranches(input, this.project, SUGGESTIONS_LIMIT)
      .then((response: BranchInfo[] | undefined) => {
        const branches = [];
        if (!response) return [];
        let branch;
        for (const key in response) {
          if (!hasOwnProperty(response, key)) {
            continue;
          }
          if (response[key].ref.startsWith('refs/heads/')) {
            branch = response[key].ref.substring('refs/heads/'.length);
          } else {
            branch = response[key].ref;
          }
          branches.push({
            name: branch,
          });
        }
        return branches;
      });
  }
}
