/**
 * @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('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) {
      this.$.restAPI.deleteFileInChangeEdit(this.change._number, this._path)
          .then(res => {
            if (!res.ok) { return; }
            this._closeDialog(this._getDialogFromEvent(e), true);
            Gerrit.Nav.navigateToChange(this.change);
          });
    },

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

    _handleRenameConfirm(e) {
      return this.$.restAPI.renameFileInChangeEdit(this.change._number,
          this._path, this._newPath).then(res => {
        if (!res.ok) { return; }
        this._closeDialog(this._getDialogFromEvent(e), 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' : '';
    },
  });
})();
