/**
 * @license
 * Copyright (C) 2017 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.
 */
(function() {
  'use strict';

  // Maximum length for patch set descriptions.
  const PATCH_DESC_MAX_LENGTH = 500;
  const MERGED_STATUS = 'MERGED';

  /**
   * @appliesMixin Gerrit.FireMixin
   * @appliesMixin Gerrit.PatchSetMixin
   */
  class GrFileListHeader extends Polymer.mixinBehaviors( [
    Gerrit.FireBehavior,
    Gerrit.PatchSetBehavior,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-file-list-header'; }
    /**
     * @event expand-diffs
     */

    /**
     * @event collapse-diffs
     */

    /**
     * @event open-diff-prefs
     */

    /**
     * @event open-included-in-dialog
     */

    /**
     * @event open-download-dialog
     */

    /**
     * @event open-upload-help-dialog
     */

    static get properties() {
      return {
        account: Object,
        allPatchSets: Array,
        /** @type {?} */
        change: Object,
        changeNum: String,
        changeUrl: String,
        changeComments: Object,
        commitInfo: Object,
        editMode: Boolean,
        loggedIn: Boolean,
        serverConfig: Object,
        shownFileCount: Number,
        diffPrefs: Object,
        diffPrefsDisabled: Boolean,
        diffViewMode: {
          type: String,
          notify: true,
        },
        patchNum: String,
        basePatchNum: String,
        filesExpanded: String,
        // Caps the number of files that can be shown and have the 'show diffs' /
        // 'hide diffs' buttons still be functional.
        _maxFilesForBulkActions: {
          type: Number,
          readOnly: true,
          value: 225,
        },
        _patchsetDescription: {
          type: String,
          value: '',
        },
        showTitle: {
          type: Boolean,
          value: true,
        },
        _descriptionReadOnly: {
          type: Boolean,
          computed: '_computeDescriptionReadOnly(loggedIn, change, account)',
        },
        revisionInfo: Object,
      };
    }

    static get observers() {
      return [
        '_computePatchSetDescription(change, patchNum)',
      ];
    }

    setDiffViewMode(mode) {
      this.$.modeSelect.setMode(mode);
    }

    _expandAllDiffs() {
      this._expanded = true;
      this.fire('expand-diffs');
    }

    _collapseAllDiffs() {
      this._expanded = false;
      this.fire('collapse-diffs');
    }

    _computeExpandedClass(filesExpanded) {
      const classes = [];
      if (filesExpanded === GrFileListConstants.FilesExpandedState.ALL) {
        classes.push('expanded');
      }
      if (filesExpanded === GrFileListConstants.FilesExpandedState.SOME ||
            filesExpanded === GrFileListConstants.FilesExpandedState.ALL) {
        classes.push('openFile');
      }
      return classes.join(' ');
    }

    _computeDescriptionPlaceholder(readOnly) {
      return (readOnly ? 'No' : 'Add') + ' patchset description';
    }

    _computeDescriptionReadOnly(loggedIn, change, account) {
      // Polymer 2: check for undefined
      if ([loggedIn, change, account].some(arg => arg === undefined)) {
        return undefined;
      }

      return !(loggedIn && (account._account_id === change.owner._account_id));
    }

    _computePatchSetDescription(change, patchNum) {
      // Polymer 2: check for undefined
      if ([change, patchNum].some(arg => arg === undefined)) {
        return;
      }

      const rev = this.getRevisionByPatchNum(change.revisions, patchNum);
      this._patchsetDescription = (rev && rev.description) ?
        rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
    }

    _handleDescriptionRemoved(e) {
      return this._updateDescription('', e);
    }

    /**
     * @param {!Object} revisions The revisions object keyed by revision hashes
     * @param {?Object} patchSet A revision already fetched from {revisions}
     * @return {string|undefined} the SHA hash corresponding to the revision.
     */
    _getPatchsetHash(revisions, patchSet) {
      for (const rev in revisions) {
        if (revisions.hasOwnProperty(rev) &&
            revisions[rev] === patchSet) {
          return rev;
        }
      }
    }

    _handleDescriptionChanged(e) {
      const desc = e.detail.trim();
      this._updateDescription(desc, e);
    }

    /**
     * Update the patchset description with the rest API.
     *
     * @param {string} desc
     * @param {?(Event|Node)} e
     * @return {!Promise}
     */
    _updateDescription(desc, e) {
      const target = Polymer.dom(e).rootTarget;
      if (target) { target.disabled = true; }
      const rev = this.getRevisionByPatchNum(this.change.revisions,
          this.patchNum);
      const sha = this._getPatchsetHash(this.change.revisions, rev);
      return this.$.restAPI.setDescription(this.changeNum, this.patchNum, desc)
          .then(res => {
            if (res.ok) {
              if (target) { target.disabled = false; }
              this.set(['change', 'revisions', sha, 'description'], desc);
              this._patchsetDescription = desc;
            }
          }).catch(err => {
            if (target) { target.disabled = false; }
            return;
          });
    }

    _computePrefsButtonHidden(prefs, diffPrefsDisabled) {
      return diffPrefsDisabled || !prefs;
    }

    _fileListActionsVisible(shownFileCount, maxFilesForBulkActions) {
      return shownFileCount <= maxFilesForBulkActions;
    }

    _handlePatchChange(e) {
      const {basePatchNum, patchNum} = e.detail;
      if (this.patchNumEquals(basePatchNum, this.basePatchNum) &&
          this.patchNumEquals(patchNum, this.patchNum)) { return; }
      Gerrit.Nav.navigateToChange(this.change, patchNum, basePatchNum);
    }

    _handlePrefsTap(e) {
      e.preventDefault();
      this.fire('open-diff-prefs');
    }

    _handleIncludedInTap(e) {
      e.preventDefault();
      this.fire('open-included-in-dialog');
    }

    _handleDownloadTap(e) {
      e.preventDefault();
      e.stopPropagation();
      this.dispatchEvent(
          new CustomEvent('open-download-dialog', {bubbles: false}));
    }

    _computeEditModeClass(editMode) {
      return editMode ? 'editMode' : '';
    }

    _computePatchInfoClass(patchNum, allPatchSets) {
      const latestNum = this.computeLatestPatchNum(allPatchSets);
      if (this.patchNumEquals(patchNum, latestNum)) {
        return '';
      }
      return 'patchInfoOldPatchSet';
    }

    _hideIncludedIn(change) {
      return change && change.status === MERGED_STATUS ? '' : 'hide';
    }

    _handleUploadTap(e) {
      e.preventDefault();
      e.stopPropagation();
      this.dispatchEvent(
          new CustomEvent('open-upload-help-dialog', {bubbles: false}));
    }

    _computeUploadHelpContainerClass(change, account) {
      const changeIsMerged = change && change.status === MERGED_STATUS;
      const ownerId = change && change.owner && change.owner._account_id ?
        change.owner._account_id : null;
      const userId = account && account._account_id;
      const userIsOwner = ownerId && userId && ownerId === userId;
      const hideContainer = !userIsOwner || changeIsMerged;
      return 'uploadContainer desktop' + (hideContainer ? ' hide' : '');
    }
  }

  customElements.define(GrFileListHeader.is, GrFileListHeader);
})();
