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

  const Defs = {};

  const NOTHING_TO_SAVE = 'No changes to save.';

  const MAX_AUTOCOMPLETE_RESULTS = 50;

  /**
   * Fired when save is a no-op
   *
   * @event show-alert
   */

  /**
   * @typedef {{
   *    value: !Object,
   * }}
   */
  Defs.rule;

  /**
   * @typedef {{
   *    rules: !Object<string, Defs.rule>
   * }}
   */
  Defs.permission;

  /**
   * Can be an empty object or consist of permissions.
   *
   * @typedef {{
   *    permissions: !Object<string, Defs.permission>
   * }}
   */
  Defs.permissions;

  /**
   * Can be an empty object or consist of permissions.
   *
   * @typedef {!Object<string, Defs.permissions>}
   */
  Defs.sections;

  /**
   * @typedef {{
   *    remove: !Defs.sections,
   *    add: !Defs.sections,
   * }}
   */
  Defs.projectAccessInput;

  Polymer({
    is: 'gr-repo-access',

    properties: {
      repo: {
        type: String,
        observer: '_repoChanged',
      },
      // The current path
      path: String,

      _canUpload: {
        type: Boolean,
        value: false,
      },
      _inheritFromFilter: String,
      _query: {
        type: Function,
        value() {
          return this._getInheritFromSuggestions.bind(this);
        },
      },
      _ownerOf: Array,
      _capabilities: Object,
      _groups: Object,
      /** @type {?} */
      _inheritsFrom: Object,
      _labels: Object,
      _local: Object,
      _editing: {
        type: Boolean,
        value: false,
        observer: '_handleEditingChanged',
      },
      _modified: {
        type: Boolean,
        value: false,
      },
      _sections: Array,
      _weblinks: Array,
      _loading: {
        type: Boolean,
        value: true,
      },
    },

    behaviors: [
      Gerrit.AccessBehavior,
      Gerrit.BaseUrlBehavior,
      Gerrit.FireBehavior,
      Gerrit.URLEncodingBehavior,
    ],

    listeners: {
      'access-modified': '_handleAccessModified',
    },

    _handleAccessModified() {
      this._modified = true;
    },

    /**
     * @param {string} repo
     * @return {!Promise}
     */
    _repoChanged(repo) {
      this._loading = true;

      if (!repo) { return Promise.resolve(); }

      return this._reload(repo);
    },

    _reload(repo) {
      const promises = [];

      const errFn = response => {
        this.fire('page-error', {response});
      };

      this._editing = false;

      // Always reset sections when a project changes.
      this._sections = [];
      promises.push(this.$.restAPI.getRepoAccessRights(repo, errFn)
          .then(res => {
            if (!res) { return Promise.resolve(); }

            // Keep a copy of the original inherit from values separate from
            // the ones data bound to gr-autocomplete, so the original value
            // can be restored if the user cancels.
            this._inheritsFrom = res.inherits_from ? Object.assign({},
                res.inherits_from) : null;
            this._originalInheritsFrom = res.inherits_from ? Object.assign({},
                res.inherits_from) : null;
            // Initialize the filter value so when the user clicks edit, the
            // current value appears. If there is no parent repo, it is
            // initialized as an empty string.
            this._inheritFromFilter = res.inherits_from ?
              this._inheritsFrom.name : '';
            this._local = res.local;
            this._groups = res.groups;
            this._weblinks = res.config_web_links || [];
            this._canUpload = res.can_upload;
            this._ownerOf = res.owner_of || [];
            return this.toSortedArray(this._local);
          }));

      promises.push(this.$.restAPI.getCapabilities(errFn)
          .then(res => {
            if (!res) { return Promise.resolve(); }

            return res;
          }));

      promises.push(this.$.restAPI.getRepo(repo, errFn)
          .then(res => {
            if (!res) { return Promise.resolve(); }

            return res.labels;
          }));

      return Promise.all(promises).then(([sections, capabilities, labels]) => {
        this._capabilities = capabilities;
        this._labels = labels;
        this._sections = sections;
        this._loading = false;
      });
    },

    _handleUpdateInheritFrom(e) {
      if (!this._inheritsFrom) {
        this._inheritsFrom = {};
      }
      this._inheritsFrom.id = e.detail.value;
      this._inheritsFrom.name = this._inheritFromFilter;
      this._handleAccessModified();
    },

    _getInheritFromSuggestions() {
      return this.$.restAPI.getRepos(
          this._inheritFromFilter,
          MAX_AUTOCOMPLETE_RESULTS)
          .then(response => {
            const projects = [];
            for (const key in response) {
              if (!response.hasOwnProperty(key)) { continue; }
              projects.push({
                name: response[key].name,
                value: response[key].id,
              });
            }
            return projects;
          });
    },

    _computeLoadingClass(loading) {
      return loading ? 'loading' : '';
    },

    _handleEdit() {
      this._editing = !this._editing;
    },

    _editOrCancel(editing) {
      return editing ? 'Cancel' : 'Edit';
    },

    _computeWebLinkClass(weblinks) {
      return weblinks && weblinks.length ? 'show' : '';
    },

    _computeShowInherit(inheritsFrom) {
      return inheritsFrom ? 'show' : '';
    },

    _handleAddedSectionRemoved(e) {
      const index = e.model.index;
      this._sections = this._sections.slice(0, index)
          .concat(this._sections.slice(index + 1, this._sections.length));
    },

    _handleEditingChanged(editing, editingOld) {
      // Ignore when editing gets set initially.
      if (!editingOld || editing) { return; }
      // Remove any unsaved but added refs.
      if (this._sections) {
        this._sections = this._sections.filter(p => !p.value.added);
      }
      // Restore inheritFrom.
      if (this._inheritsFrom) {
        this._inheritsFrom = Object.assign({}, this._originalInheritsFrom);
        this._inheritFromFilter = this._inheritsFrom.name;
      }
      for (const key of Object.keys(this._local)) {
        if (this._local[key].added) {
          delete this._local[key];
        }
      }
    },

    /**
     * @param {!Defs.projectAccessInput} addRemoveObj
     * @param {!Array} path
     * @param {string} type add or remove
     * @param {!Object=} opt_value value to add if the type is 'add'
     * @return {!Defs.projectAccessInput}
     */
    _updateAddRemoveObj(addRemoveObj, path, type, opt_value) {
      let curPos = addRemoveObj[type];
      for (const item of path) {
        if (!curPos[item]) {
          if (item === path[path.length - 1] && type === 'remove') {
            if (path[path.length - 2] === 'permissions') {
              curPos[item] = {rules: {}};
            } else if (path.length === 1) {
              curPos[item] = {permissions: {}};
            } else {
              curPos[item] = {};
            }
          } else if (item === path[path.length - 1] && type === 'add') {
            curPos[item] = opt_value;
          } else {
            curPos[item] = {};
          }
        }
        curPos = curPos[item];
      }
      return addRemoveObj;
    },

    /**
     * Used to recursively remove any objects with a 'deleted' bit.
     */
    _recursivelyRemoveDeleted(obj) {
      for (const k in obj) {
        if (!obj.hasOwnProperty(k)) { continue; }

        if (typeof obj[k] == 'object') {
          if (obj[k].deleted) {
            delete obj[k];
            return;
          }
          this._recursivelyRemoveDeleted(obj[k]);
        }
      }
    },

    _recursivelyUpdateAddRemoveObj(obj, addRemoveObj, path = []) {
      for (const k in obj) {
        if (!obj.hasOwnProperty(k)) { continue; }
        if (typeof obj[k] == 'object') {
          const updatedId = obj[k].updatedId;
          const ref = updatedId ? updatedId : k;
          if (obj[k].deleted) {
            this._updateAddRemoveObj(addRemoveObj,
                path.concat(k), 'remove');
            continue;
          } else if (obj[k].modified) {
            this._updateAddRemoveObj(addRemoveObj,
                path.concat(k), 'remove');
            this._updateAddRemoveObj(addRemoveObj, path.concat(ref), 'add',
                obj[k]);
            /* Special case for ref changes because they need to be added and
             removed in a different way. The new ref needs to include all
             changes but also the initial state. To do this, instead of
             continuing with the same recursion, just remove anything that is
             deleted in the current state. */
            if (updatedId && updatedId !== k) {
              this._recursivelyRemoveDeleted(addRemoveObj.add[updatedId]);
            }
            continue;
          } else if (obj[k].added) {
            this._updateAddRemoveObj(addRemoveObj,
                path.concat(ref), 'add', obj[k]);
            /**
             * As add / delete both can happen in the new section,
             * so here to make sure it will remove the deleted ones.
             * @see Issue 11339
             */
            this._recursivelyRemoveDeleted(addRemoveObj.add[k]);
            continue;
          }
          this._recursivelyUpdateAddRemoveObj(obj[k], addRemoveObj,
              path.concat(k));
        }
      }
    },

    /**
     * Returns an object formatted for saving or submitting access changes for
     * review
     *
     * @return {!Defs.projectAccessInput}
     */
    _computeAddAndRemove() {
      const addRemoveObj = {
        add: {},
        remove: {},
      };

      const originalInheritsFromId = this._originalInheritsFrom ?
        this.singleDecodeURL(this._originalInheritsFrom.id) :
        null;
      const inheritsFromId = this._inheritsFrom ?
        this.singleDecodeURL(this._inheritsFrom.id) :
        null;

      const inheritFromChanged =
          // Inherit from changed
          (originalInheritsFromId
              && originalInheritsFromId !== inheritsFromId) ||
          // Inherit from added (did not have one initially);
          (!originalInheritsFromId && inheritsFromId);

      this._recursivelyUpdateAddRemoveObj(this._local, addRemoveObj);

      if (inheritFromChanged) {
        addRemoveObj.parent = inheritsFromId;
      }
      return addRemoveObj;
    },

    _handleCreateSection() {
      let newRef = 'refs/for/*';
      // Avoid using an already used key for the placeholder, since it
      // immediately gets added to an object.
      while (this._local[newRef]) {
        newRef = `${newRef}*`;
      }
      const section = {permissions: {}, added: true};
      this.push('_sections', {id: newRef, value: section});
      this.set(['_local', newRef], section);
      Polymer.dom.flush();
      Polymer.dom(this.root).querySelector('gr-access-section:last-of-type')
          .editReference();
    },

    _getObjforSave() {
      const addRemoveObj = this._computeAddAndRemove();
      // If there are no changes, don't actually save.
      if (!Object.keys(addRemoveObj.add).length &&
          !Object.keys(addRemoveObj.remove).length &&
          !addRemoveObj.parent) {
        this.dispatchEvent(new CustomEvent('show-alert', {
          detail: {message: NOTHING_TO_SAVE},
          bubbles: true,
          composed: true,
        }));
        return;
      }
      const obj = {
        add: addRemoveObj.add,
        remove: addRemoveObj.remove,
      };
      if (addRemoveObj.parent) {
        obj.parent = addRemoveObj.parent;
      }
      return obj;
    },

    _handleSave() {
      const obj = this._getObjforSave();
      if (!obj) { return; }
      return this.$.restAPI.setRepoAccessRights(this.repo, obj)
          .then(() => {
            this._reload(this.repo);
          });
    },

    _handleSaveForReview() {
      const obj = this._getObjforSave();
      if (!obj) { return; }
      return this.$.restAPI.setRepoAccessRightsForReview(this.repo, obj)
          .then(change => {
            Gerrit.Nav.navigateToChange(change);
          });
    },

    _computeSaveReviewBtnClass(canUpload) {
      return !canUpload ? 'invisible' : '';
    },

    _computeSaveBtnClass(ownerOf) {
      return ownerOf && ownerOf.length === 0 ? 'invisible' : '';
    },

    _computeMainClass(ownerOf, canUpload, editing) {
      const classList = [];
      if (ownerOf && ownerOf.length > 0 || canUpload) {
        classList.push('admin');
      }
      if (editing) {
        classList.push('editing');
      }
      return classList.join(' ');
    },

    _computeParentHref(repoName) {
      return this.getBaseUrl() +
          `/admin/repos/${this.encodeURL(repoName, true)},access`;
    },
  });
})();
