/**
 * @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 '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '../../../styles/gr-form-styles.js';
import '../../../styles/gr-subpage-styles.js';
import '../../../styles/gr-table-styles.js';
import '../../../styles/shared-styles.js';
import '../../shared/gr-account-link/gr-account-link.js';
import '../../shared/gr-autocomplete/gr-autocomplete.js';
import '../../shared/gr-button/gr-button.js';
import '../../shared/gr-overlay/gr-overlay.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.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-group-members_html.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {URLEncodingBehavior} from '../../../behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.js';

const SUGGESTIONS_LIMIT = 15;
const SAVING_ERROR_TEXT = 'Group may not exist, or you may not have '+
    'permission to add it';

const URL_REGEX = '^(?:[a-z]+:)?//';

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

  static get is() { return 'gr-group-members'; }

  static get properties() {
    return {
      groupId: Number,
      _groupMemberSearchId: String,
      _groupMemberSearchName: String,
      _includedGroupSearchId: String,
      _includedGroupSearchName: String,
      _loading: {
        type: Boolean,
        value: true,
      },
      _groupName: String,
      _groupMembers: Object,
      _includedGroups: Object,
      _itemName: String,
      _itemType: String,
      _queryMembers: {
        type: Function,
        value() {
          return this._getAccountSuggestions.bind(this);
        },
      },
      _queryIncludedGroup: {
        type: Function,
        value() {
          return this._getGroupSuggestions.bind(this);
        },
      },
      _groupOwner: {
        type: Boolean,
        value: false,
      },
      _isAdmin: {
        type: Boolean,
        value: false,
      },
    };
  }

  /** @override */
  attached() {
    super.attached();
    this._loadGroupDetails();

    this.dispatchEvent(new CustomEvent('title-change', {
      detail: {title: 'Members'},
      composed: true, bubbles: true,
    }));
  }

  _loadGroupDetails() {
    if (!this.groupId) { return; }

    const promises = [];

    const errFn = response => {
      this.dispatchEvent(new CustomEvent('page-error', {
        detail: {response},
        composed: true, bubbles: true,
      }));
    };

    return this.$.restAPI.getGroupConfig(this.groupId, errFn)
        .then(config => {
          if (!config || !config.name) { return Promise.resolve(); }

          this._groupName = config.name;

          promises.push(this.$.restAPI.getIsAdmin().then(isAdmin => {
            this._isAdmin = !!isAdmin;
          }));

          promises.push(this.$.restAPI.getIsGroupOwner(config.name)
              .then(isOwner => {
                this._groupOwner = !!isOwner;
              }));

          promises.push(this.$.restAPI.getGroupMembers(config.name).then(
              members => {
                this._groupMembers = members;
              }));

          promises.push(this.$.restAPI.getIncludedGroup(config.name)
              .then(includedGroup => {
                this._includedGroups = includedGroup;
              }));

          return Promise.all(promises).then(() => {
            this._loading = false;
          });
        });
  }

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

  _isLoading() {
    return this._loading || this._loading === undefined;
  }

  _computeGroupUrl(url) {
    if (!url) { return; }

    const r = new RegExp(URL_REGEX, 'i');
    if (r.test(url)) {
      return url;
    }

    // For GWT compatibility
    if (url.startsWith('#')) {
      return this.getBaseUrl() + url.slice(1);
    }
    return this.getBaseUrl() + url;
  }

  _handleSavingGroupMember() {
    return this.$.restAPI.saveGroupMembers(this._groupName,
        this._groupMemberSearchId).then(config => {
      if (!config) {
        return;
      }
      this.$.restAPI.getGroupMembers(this._groupName).then(members => {
        this._groupMembers = members;
      });
      this._groupMemberSearchName = '';
      this._groupMemberSearchId = '';
    });
  }

  _handleDeleteConfirm() {
    this.$.overlay.close();
    if (this._itemType === 'member') {
      return this.$.restAPI.deleteGroupMembers(this._groupName,
          this._itemId)
          .then(itemDeleted => {
            if (itemDeleted.status === 204) {
              this.$.restAPI.getGroupMembers(this._groupName)
                  .then(members => {
                    this._groupMembers = members;
                  });
            }
          });
    } else if (this._itemType === 'includedGroup') {
      return this.$.restAPI.deleteIncludedGroup(this._groupName,
          this._itemId)
          .then(itemDeleted => {
            if (itemDeleted.status === 204 || itemDeleted.status === 205) {
              this.$.restAPI.getIncludedGroup(this._groupName)
                  .then(includedGroup => {
                    this._includedGroups = includedGroup;
                  });
            }
          });
    }
  }

  _handleConfirmDialogCancel() {
    this.$.overlay.close();
  }

  _handleDeleteMember(e) {
    const id = e.model.get('item._account_id');
    const name = e.model.get('item.name');
    const username = e.model.get('item.username');
    const email = e.model.get('item.email');
    const item = username || name || email || id;
    if (!item) {
      return '';
    }
    this._itemName = item;
    this._itemId = id;
    this._itemType = 'member';
    this.$.overlay.open();
  }

  _handleSavingIncludedGroups() {
    return this.$.restAPI.saveIncludedGroup(this._groupName,
        this._includedGroupSearchId.replace(/\+/g, ' '), err => {
          if (err.status === 404) {
            this.dispatchEvent(new CustomEvent('show-alert', {
              detail: {message: SAVING_ERROR_TEXT},
              bubbles: true,
              composed: true,
            }));
            return err;
          }
          throw Error(err.statusText);
        })
        .then(config => {
          if (!config) {
            return;
          }
          this.$.restAPI.getIncludedGroup(this._groupName)
              .then(includedGroup => {
                this._includedGroups = includedGroup;
              });
          this._includedGroupSearchName = '';
          this._includedGroupSearchId = '';
        });
  }

  _handleDeleteIncludedGroup(e) {
    const id = decodeURIComponent(e.model.get('item.id')).replace(/\+/g, ' ');
    const name = e.model.get('item.name');
    const item = name || id;
    if (!item) { return ''; }
    this._itemName = item;
    this._itemId = id;
    this._itemType = 'includedGroup';
    this.$.overlay.open();
  }

  _getAccountSuggestions(input) {
    if (input.length === 0) { return Promise.resolve([]); }
    return this.$.restAPI.getSuggestedAccounts(
        input, SUGGESTIONS_LIMIT).then(accounts => {
      const accountSuggestions = [];
      let nameAndEmail;
      if (!accounts) { return []; }
      for (const key in accounts) {
        if (!accounts.hasOwnProperty(key)) { continue; }
        if (accounts[key].email !== undefined) {
          nameAndEmail = accounts[key].name +
                ' <' + accounts[key].email + '>';
        } else {
          nameAndEmail = accounts[key].name;
        }
        accountSuggestions.push({
          name: nameAndEmail,
          value: accounts[key]._account_id,
        });
      }
      return accountSuggestions;
    });
  }

  _getGroupSuggestions(input) {
    return this.$.restAPI.getSuggestedGroups(input)
        .then(response => {
          const groups = [];
          for (const key in response) {
            if (!response.hasOwnProperty(key)) { continue; }
            groups.push({
              name: key,
              value: decodeURIComponent(response[key].id),
            });
          }
          return groups;
        });
  }

  _computeHideItemClass(owner, admin) {
    return admin || owner ? '' : 'canModify';
  }
}

customElements.define(GrGroupMembers.is, GrGroupMembers);
