/**
 * @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';

  /**
   * @appliesMixin Gerrit.PatchSetMixin
   * @extends Polymer.Element
   */
  class GrEditControls extends Polymer.mixinBehaviors( [
    Gerrit.PatchSetBehavior,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-edit-controls'; }

    static get properties() {
      return {
        change: Object,
        patchNum: String,

        /**
         * TODO(kaspern): by default, the RESTORE action should be hidden in the
         * file-list as it is a per-file action only. Remove this default value
         * when the Actions dictionary is moved to a shared constants file and
         * use the hiddenActions property in the parent component.
         */
        hiddenActions: {
          type: Array,
          value() { return [GrEditConstants.Actions.RESTORE.id]; },
        },

        _actions: {
          type: Array,
          value() { return Object.values(GrEditConstants.Actions); },
        },
        _path: {
          type: String,
          value: '',
        },
        _newPath: {
          type: String,
          value: '',
        },
        _query: {
          type: Function,
          value() {
            return this._queryFiles.bind(this);
          },
        },
      };
    }

    _handleTap(e) {
      e.preventDefault();
      const action = Polymer.dom(e).localTarget.id;
      switch (action) {
        case GrEditConstants.Actions.OPEN.id:
          this.openOpenDialog();
          return;
        case GrEditConstants.Actions.DELETE.id:
          this.openDeleteDialog();
          return;
        case GrEditConstants.Actions.RENAME.id:
          this.openRenameDialog();
          return;
        case GrEditConstants.Actions.RESTORE.id:
          this.openRestoreDialog();
          return;
      }
    }

    /**
     * @param {string=} opt_path
     */
    openOpenDialog(opt_path) {
      if (opt_path) { this._path = opt_path; }
      return this._showDialog(this.$.openDialog);
    }

    /**
     * @param {string=} opt_path
     */
    openDeleteDialog(opt_path) {
      if (opt_path) { this._path = opt_path; }
      return this._showDialog(this.$.deleteDialog);
    }

    /**
     * @param {string=} opt_path
     */
    openRenameDialog(opt_path) {
      if (opt_path) { this._path = opt_path; }
      return this._showDialog(this.$.renameDialog);
    }

    /**
     * @param {string=} opt_path
     */
    openRestoreDialog(opt_path) {
      if (opt_path) { this._path = opt_path; }
      return this._showDialog(this.$.restoreDialog);
    }

    /**
     * Given a path string, checks that it is a valid file path.
     *
     * @param {string} path
     * @return {boolean}
     */
    _isValidPath(path) {
      // Double negation needed for strict boolean return type.
      return !!path.length && !path.endsWith('/');
    }

    _computeRenameDisabled(path, newPath) {
      return this._isValidPath(path) && this._isValidPath(newPath);
    }

    /**
     * Given a dom event, gets the dialog that lies along this event path.
     *
     * @param {!Event} e
     * @return {!Element|undefined}
     */
    _getDialogFromEvent(e) {
      return Polymer.dom(e).path.find(element => {
        if (!element.classList) { return false; }
        return element.classList.contains('dialog');
      });
    }

    _showDialog(dialog) {
      // Some dialogs may not fire their on-close event when closed in certain
      // ways (e.g. by clicking outside the dialog body). This call prevents
      // multiple dialogs from being shown in the same overlay.
      this._hideAllDialogs();

      return this.$.overlay.open().then(() => {
        dialog.classList.toggle('invisible', false);
        const autocomplete = dialog.querySelector('gr-autocomplete');
        if (autocomplete) { autocomplete.focus(); }
        this.async(() => { this.$.overlay.center(); }, 1);
      });
    }

    _hideAllDialogs() {
      const dialogs = Polymer.dom(this.root).querySelectorAll('.dialog');
      for (const dialog of dialogs) { this._closeDialog(dialog); }
    }

    /**
     * @param {Element|undefined} dialog
     * @param {boolean=} clearInputs
     */
    _closeDialog(dialog, clearInputs) {
      if (!dialog) { return; }

      if (clearInputs) {
        // Dialog may have autocompletes and plain inputs -- as these have
        // different properties representing their bound text, it is easier to
        // just make two separate queries.
        dialog.querySelectorAll('gr-autocomplete')
            .forEach(input => { input.text = ''; });

        dialog.querySelectorAll('iron-input')
            .forEach(input => { input.bindValue = ''; });
      }

      dialog.classList.toggle('invisible', true);
      return this.$.overlay.close();
    }

    _handleDialogCancel(e) {
      this._closeDialog(this._getDialogFromEvent(e));
    }

    _handleOpenConfirm(e) {
      const url = Gerrit.Nav.getEditUrlForDiff(this.change, this._path,
          this.patchNum);
      Gerrit.Nav.navigateToRelativeUrl(url);
      this._closeDialog(this._getDialogFromEvent(e), true);
    }

    _handleDeleteConfirm(e) {
      // Get the dialog before the api call as the event will change during bubbling
      // which will make Polymer.dom(e).path an emtpy array in polymer 2
      const dialog = this._getDialogFromEvent(e);
      this.$.restAPI.deleteFileInChangeEdit(this.change._number, this._path)
          .then(res => {
            if (!res.ok) { return; }
            this._closeDialog(dialog, true);
            Gerrit.Nav.navigateToChange(this.change);
          });
    }

    _handleRestoreConfirm(e) {
      const dialog = this._getDialogFromEvent(e);
      this.$.restAPI.restoreFileInChangeEdit(this.change._number, this._path)
          .then(res => {
            if (!res.ok) { return; }
            this._closeDialog(dialog, true);
            Gerrit.Nav.navigateToChange(this.change);
          });
    }

    _handleRenameConfirm(e) {
      const dialog = this._getDialogFromEvent(e);
      return this.$.restAPI.renameFileInChangeEdit(this.change._number,
          this._path, this._newPath).then(res => {
        if (!res.ok) { return; }
        this._closeDialog(dialog, true);
        Gerrit.Nav.navigateToChange(this.change);
      });
    }

    _queryFiles(input) {
      return this.$.restAPI.queryChangeFiles(this.change._number,
          this.patchNum, input).then(res => res.map(file => {
        return {name: file};
      }));
    }

    _computeIsInvisible(id, hiddenActions) {
      return hiddenActions.includes(id) ? 'invisible' : '';
    }
  }

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