/**
 * @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.
 */
import '../../../scripts/bundled-polymer.js';

import '../../../styles/gr-menu-page-styles.js';
import '../../../styles/gr-subpage-styles.js';
import '../../../styles/shared-styles.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../gr-access-section/gr-access-section.js';
import {flush, dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-repo-access_html.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {AccessBehavior} from '../../../behaviors/gr-access-behavior/gr-access-behavior.js';
import {URLEncodingBehavior} from '../../../behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';

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;

/**
 * @extends Polymer.Element
 */
class GrRepoAccess extends mixinBehaviors( [
  AccessBehavior,
  BaseUrlBehavior,
  URLEncodingBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-repo-access'; }

  static get properties() {
    return {
      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,
      },
    };
  }

  /** @override */
  created() {
    super.created();
    this.addEventListener('access-modified',
        () =>
          this._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.dispatchEvent(new CustomEvent('page-error', {
        detail: {response},
        composed: true, bubbles: true,
      }));
    };

    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);
    flush();
    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(e) {
    const obj = this._getObjforSave();
    if (!obj) { return; }
    const button = e && e.target;
    if (button) {
      button.loading = true;
    }
    return this.$.restAPI.setRepoAccessRights(this.repo, obj)
        .then(() => {
          this._reload(this.repo);
        })
        .finally(() => {
          this._modified = false;
          if (button) {
            button.loading = false;
          }
        });
  }

  _handleSaveForReview(e) {
    const obj = this._getObjforSave();
    if (!obj) { return; }
    const button = e && e.target;
    if (button) {
      button.loading = true;
    }
    return this.$.restAPI
        .setRepoAccessRightsForReview(this.repo, obj)
        .then(change => {
          GerritNav.navigateToChange(change);
        })
        .finally(() => {
          this._modified = false;
          if (button) {
            button.loading = false;
          }
        });
  }

  _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`;
  }
}

customElements.define(GrRepoAccess.is, GrRepoAccess);
