/**
 * @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 '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../../styles/shared-styles.js';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.js';
import '../../plugins/gr-endpoint-param/gr-endpoint-param.js';
import '../../plugins/gr-endpoint-slot/gr-endpoint-slot.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-related-changes-list_html.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {ChangeStatus} from '../../../constants/constants.js';
import {patchNumEquals} from '../../../utils/patch-set-util.js';
import {changeIsOpen} from '../../../utils/change-util.js';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';

/**
 * @extends PolymerElement
 */
class GrRelatedChangesList extends GestureEventListeners(
    LegacyElementMixin(PolymerElement)) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-related-changes-list'; }
  /**
   * Fired when a new section is loaded so that the change view can determine
   * a show more button is needed, sometimes before all the sections finish
   * loading.
   *
   * @event new-section-loaded
   */

  static get properties() {
    return {
      change: Object,
      hasParent: {
        type: Boolean,
        notify: true,
        value: false,
      },
      patchNum: String,
      parentChange: Object,
      hidden: {
        type: Boolean,
        value: false,
        reflectToAttribute: true,
      },
      loading: {
        type: Boolean,
        notify: true,
      },
      mergeable: Boolean,
      _connectedRevisions: {
        type: Array,
        computed: '_computeConnectedRevisions(change, patchNum, ' +
          '_relatedResponse.changes)',
      },
      /** @type {?} */
      _relatedResponse: {
        type: Object,
        value() { return {changes: []}; },
      },
      /** @type {?} */
      _submittedTogether: {
        type: Object,
        value() { return {changes: []}; },
      },
      _conflicts: {
        type: Array,
        value() { return []; },
      },
      _cherryPicks: {
        type: Array,
        value() { return []; },
      },
      _sameTopic: {
        type: Array,
        value() { return []; },
      },
    };
  }

  static get observers() {
    return [
      '_resultsChanged(_relatedResponse, _submittedTogether, ' +
        '_conflicts, _cherryPicks, _sameTopic)',
    ];
  }

  clear() {
    this.loading = true;
    this.hidden = true;

    this._relatedResponse = {changes: []};
    this._submittedTogether = {changes: []};
    this._conflicts = [];
    this._cherryPicks = [];
    this._sameTopic = [];
  }

  reload() {
    if (!this.change || !this.patchNum) {
      return Promise.resolve();
    }
    this.loading = true;
    const promises = [
      this._getRelatedChanges().then(response => {
        this._relatedResponse = response;
        this._fireReloadEvent();
        this.hasParent = this._calculateHasParent(this.change.change_id,
            response.changes);
      }),
      this._getSubmittedTogether().then(response => {
        this._submittedTogether = response;
        this._fireReloadEvent();
      }),
      this._getCherryPicks().then(response => {
        this._cherryPicks = response;
        this._fireReloadEvent();
      }),
    ];

    // Get conflicts if change is open and is mergeable.
    if (changeIsOpen(this.change) && this.mergeable) {
      promises.push(this._getConflicts().then(response => {
        // Because the server doesn't always return a response and the
        // template expects an array, always return an array.
        this._conflicts = response ? response : [];
        this._fireReloadEvent();
      }));
    }

    promises.push(this._getServerConfig().then(config => {
      if (this.change.topic && !config.change.submit_whole_topic) {
        return this._getChangesWithSameTopic().then(response => {
          this._sameTopic = response;
        });
      } else {
        this._sameTopic = [];
      }
      return this._sameTopic;
    }));

    return Promise.all(promises).then(() => {
      this.loading = false;
    });
  }

  _fireReloadEvent() {
    // The listener on the change computes height of the related changes
    // section, so they have to be rendered first, and inside a dom-repeat,
    // that requires a flush.
    flush();
    this.dispatchEvent(new CustomEvent('new-section-loaded'));
  }

  /**
   * Determines whether or not the given change has a parent change. If there
   * is a relation chain, and the change id is not the last item of the
   * relation chain, there is a parent.
   *
   * @param  {number} currentChangeId
   * @param  {!Array} relatedChanges
   * @return {boolean}
   */
  _calculateHasParent(currentChangeId, relatedChanges) {
    return relatedChanges.length > 0 &&
        relatedChanges[relatedChanges.length - 1].change_id !==
        currentChangeId;
  }

  _getRelatedChanges() {
    return this.$.restAPI.getRelatedChanges(this.change._number,
        this.patchNum);
  }

  _getSubmittedTogether() {
    return this.$.restAPI.getChangesSubmittedTogether(this.change._number);
  }

  _getServerConfig() {
    return this.$.restAPI.getConfig();
  }

  _getConflicts() {
    return this.$.restAPI.getChangeConflicts(this.change._number);
  }

  _getCherryPicks() {
    return this.$.restAPI.getChangeCherryPicks(this.change.project,
        this.change.change_id, this.change._number);
  }

  _getChangesWithSameTopic() {
    return this.$.restAPI.getChangesWithSameTopic(this.change.topic,
        this.change._number);
  }

  /**
   * @param {number} changeNum
   * @param {string} project
   * @param {number=} opt_patchNum
   * @return {string}
   */
  _computeChangeURL(changeNum, project, opt_patchNum) {
    return GerritNav.getUrlForChangeById(changeNum, project, opt_patchNum);
  }

  /**
   * Do the given objects describe the same change? Compares the changes by
   * their numbers.
   *
   * @see /Documentation/rest-api-changes.html#change-info
   * @see /Documentation/rest-api-changes.html#related-change-and-commit-info
   * @param {!Object} a Either ChangeInfo or RelatedChangeAndCommitInfo
   * @param {!Object} b Either ChangeInfo or RelatedChangeAndCommitInfo
   * @return {boolean}
   */
  _changesEqual(a, b) {
    const aNum = this._getChangeNumber(a);
    const bNum = this._getChangeNumber(b);
    return aNum === bNum;
  }

  /**
   * Get the change number from either a ChangeInfo (such as those included in
   * SubmittedTogetherInfo responses) or get the change number from a
   * RelatedChangeAndCommitInfo (such as those included in a
   * RelatedChangesInfo response).
   *
   * @see /Documentation/rest-api-changes.html#change-info
   * @see /Documentation/rest-api-changes.html#related-change-and-commit-info
   *
   * @param {!Object} change Either a ChangeInfo or a
   *     RelatedChangeAndCommitInfo object.
   * @return {number}
   */
  _getChangeNumber(change) {
    // Default to 0 if change property is not defined.
    if (!change) return 0;

    if (change.hasOwnProperty('_change_number')) {
      return change._change_number;
    }
    return change._number;
  }

  _computeLinkClass(change) {
    const statuses = [];
    if (change.status == ChangeStatus.ABANDONED) {
      statuses.push('strikethrough');
    }
    if (change.submittable) {
      statuses.push('submittable');
    }
    return statuses.join(' ');
  }

  _computeChangeStatusClass(change) {
    const classes = ['status'];
    if (change._revision_number != change._current_revision_number) {
      classes.push('notCurrent');
    } else if (this._isIndirectAncestor(change)) {
      classes.push('indirectAncestor');
    } else if (change.submittable) {
      classes.push('submittable');
    } else if (change.status == ChangeStatus.NEW) {
      classes.push('hidden');
    }
    return classes.join(' ');
  }

  _computeChangeStatus(change) {
    switch (change.status) {
      case ChangeStatus.MERGED:
        return 'Merged';
      case ChangeStatus.ABANDONED:
        return 'Abandoned';
    }
    if (change._revision_number != change._current_revision_number) {
      return 'Not current';
    } else if (this._isIndirectAncestor(change)) {
      return 'Indirect ancestor';
    } else if (change.submittable) {
      return 'Submittable';
    }
    return '';
  }

  /** @override */
  attached() {
    super.attached();
    // We listen to `new-section-loaded` events to allow plugins to trigger
    // visibility computations, if their content or visibility changed.
    this.addEventListener('new-section-loaded',
        () => this._handleNewSectionLoaded());
  }

  _handleNewSectionLoaded() {
    // A plugin sent a `new-section-loaded` event, so its visibility likely
    // changed. Hence, we update our visibility if needed.
    this._resultsChanged(this._relatedResponse, this._submittedTogether,
        this._conflicts, this._cherryPicks, this._sameTopic);
  }

  _resultsChanged(related, submittedTogether, conflicts,
      cherryPicks, sameTopic) {
    // Polymer 2: check for undefined
    if ([
      related,
      submittedTogether,
      conflicts,
      cherryPicks,
      sameTopic,
    ].includes(undefined)) {
      return;
    }

    const results = [
      related && related.changes,
      // If there are either visible or non-visible changes, we need a
      // non-empty list to fire the event and set visibility.
      submittedTogether && ((submittedTogether.changes || [])
          + (submittedTogether.non_visible_changes ? [{}] : [])),
      conflicts,
      cherryPicks,
      sameTopic,
    ];
    for (let i = 0; i < results.length; i++) {
      if (results[i] && results[i].length > 0) {
        this.hidden = false;
        this.dispatchEvent(new CustomEvent('update', {
          composed: true, bubbles: false,
        }));
        return;
      }
    }

    this._computeHidden();
  }

  _computeHidden() {
    // None of the built-in change lists had elements. So all of them are
    // hidden. But since plugins might have injected visible content, we need
    // to check for that and stay visible if we find any such visible content.
    // (We consider plugins visible except if it's main element has the hidden
    // attribute set to true.)
    const plugins = getPluginEndpoints().getDetails('related-changes-section');
    this.hidden = !(plugins.some(plugin => (
      (!plugin.domHook)
        || plugin.domHook.getAllAttached().some(
            instance => !instance.hidden))));
  }

  _isIndirectAncestor(change) {
    return !this._connectedRevisions.includes(change.commit.commit);
  }

  _computeConnectedRevisions(change, patchNum, relatedChanges) {
    // Polymer 2: check for undefined
    if ([change, patchNum, relatedChanges].includes(undefined)) {
      return undefined;
    }

    const connected = [];
    let changeRevision;
    if (!change) { return []; }
    for (const rev in change.revisions) {
      if (patchNumEquals(change.revisions[rev]._number, patchNum)) {
        changeRevision = rev;
      }
    }
    const commits = relatedChanges.map(c => c.commit);
    let pos = commits.length - 1;

    while (pos >= 0) {
      const commit = commits[pos].commit;
      connected.push(commit);
      if (commit == changeRevision) {
        break;
      }
      pos--;
    }
    while (pos >= 0) {
      for (let i = 0; i < commits[pos].parents.length; i++) {
        if (connected.includes(commits[pos].parents[i].commit)) {
          connected.push(commits[pos].commit);
          break;
        }
      }
      --pos;
    }
    return connected;
  }

  _computeSubmittedTogetherClass(submittedTogether) {
    if (!submittedTogether || (
      submittedTogether.changes.length === 0 &&
        !submittedTogether.non_visible_changes)) {
      return 'hidden';
    }
    return '';
  }

  _computeNonVisibleChangesNote(n) {
    const noun = n === 1 ? 'change' : 'changes';
    return `(+ ${n} non-visible ${noun})`;
  }
}

customElements.define(GrRelatedChangesList.is, GrRelatedChangesList);
