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

  Polymer({
    is: 'gr-edit-controls',

    properties: {
      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);
        },
      },
    },

    behaviors: [
      Gerrit.PatchSetBehavior,
    ],

    _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' : '';
    },
  });
})();
