/**
 * @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';
import '../../../styles/gr-form-styles';
import '../../../styles/gr-subpage-styles';
import '../../../styles/gr-table-styles';
import '../../../styles/shared-styles';
import '../../shared/gr-account-link/gr-account-link';
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-overlay/gr-overlay';
import '../gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-group-members_html';
import {getBaseUrl} from '../../../utils/url-util';
import {customElement, property} from '@polymer/decorators';
import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
import {
  GroupId,
  AccountId,
  AccountInfo,
  GroupInfo,
  GroupName,
} from '../../../types/common';
import {
  AutocompleteQuery,
  AutocompleteSuggestion,
} from '../../shared/gr-autocomplete/gr-autocomplete';
import {PolymerDomRepeatEvent} from '../../../types/types';
import {
  fireAlert,
  firePageError,
  fireTitleChange,
} from '../../../utils/event-util';
import {appContext} from '../../../services/app-context';
import {ErrorCallback} from '../../../api/rest';
import {assertNever} from '../../../utils/common-util';

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]+:)?//';

export enum ItemType {
  MEMBER = 'member',
  INCLUDED_GROUP = 'includedGroup',
}

export interface GrGroupMembers {
  $: {
    overlay: GrOverlay;
  };
}
@customElement('gr-group-members')
export class GrGroupMembers extends PolymerElement {
  static get template() {
    return htmlTemplate;
  }

  @property({type: Number})
  groupId?: GroupId;

  @property({type: Number})
  _groupMemberSearchId?: number;

  @property({type: String})
  _groupMemberSearchName?: string;

  @property({type: String})
  _includedGroupSearchId?: string;

  @property({type: String})
  _includedGroupSearchName?: string;

  @property({type: Boolean})
  _loading = true;

  @property({type: String})
  _groupName?: GroupName;

  @property({type: Object})
  _groupMembers?: AccountInfo[];

  @property({type: Object})
  _includedGroups?: GroupInfo[];

  @property({type: String})
  _itemName?: string;

  @property({type: String})
  _itemType?: ItemType;

  @property({type: Object})
  _queryMembers: AutocompleteQuery;

  @property({type: Object})
  _queryIncludedGroup: AutocompleteQuery;

  @property({type: Boolean})
  _groupOwner = false;

  @property({type: Boolean})
  _isAdmin = false;

  _itemId?: AccountId | GroupId;

  private readonly restApiService = appContext.restApiService;

  constructor() {
    super();
    this._queryMembers = input => this._getAccountSuggestions(input);
    this._queryIncludedGroup = input => this._getGroupSuggestions(input);
  }

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

    fireTitleChange(this, 'Members');
  }

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

    const promises: Promise<void>[] = [];

    const errFn: ErrorCallback = response => {
      firePageError(response);
    };

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

        this._groupName = config.name;

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

        promises.push(
          this.restApiService.getIsGroupOwner(this._groupName).then(isOwner => {
            this._groupOwner = !!isOwner;
          })
        );

        promises.push(
          this.restApiService.getGroupMembers(this._groupName).then(members => {
            this._groupMembers = members;
          })
        );

        promises.push(
          this.restApiService
            .getIncludedGroup(this._groupName)
            .then(includedGroup => {
              this._includedGroups = includedGroup;
            })
        );

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

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

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

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

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

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

  _handleSavingGroupMember() {
    if (!this._groupName) {
      return Promise.reject(new Error('group name undefined'));
    }
    return this.restApiService
      .saveGroupMember(this._groupName, this._groupMemberSearchId as AccountId)
      .then(config => {
        if (!config || !this._groupName) {
          return;
        }
        this.restApiService.getGroupMembers(this._groupName).then(members => {
          this._groupMembers = members;
        });
        this._groupMemberSearchName = '';
        this._groupMemberSearchId = undefined;
      });
  }

  _handleDeleteConfirm() {
    if (!this._groupName) {
      return Promise.reject(new Error('group name undefined'));
    }
    this.$.overlay.close();
    if (this._itemType === ItemType.MEMBER) {
      return this.restApiService
        .deleteGroupMember(this._groupName, this._itemId! as AccountId)
        .then(itemDeleted => {
          if (itemDeleted.status === 204 && this._groupName) {
            this.restApiService
              .getGroupMembers(this._groupName)
              .then(members => {
                this._groupMembers = members;
              });
          }
        });
    } else if (this._itemType === ItemType.INCLUDED_GROUP) {
      return this.restApiService
        .deleteIncludedGroup(this._groupName, this._itemId! as GroupId)
        .then(itemDeleted => {
          if (
            (itemDeleted.status === 204 || itemDeleted.status === 205) &&
            this._groupName
          ) {
            this.restApiService
              .getIncludedGroup(this._groupName)
              .then(includedGroup => {
                this._includedGroups = includedGroup;
              });
          }
        });
    }
    return Promise.reject(new Error('Unrecognized item type'));
  }

  _computeItemTypeName(itemType?: ItemType): string {
    if (itemType === undefined) return '';
    switch (itemType) {
      case ItemType.INCLUDED_GROUP:
        return 'Included Group';
      case ItemType.MEMBER:
        return 'Member';
      default:
        assertNever(itemType, 'unknown item type: ${itemType}');
    }
  }

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

  _handleDeleteMember(e: PolymerDomRepeatEvent<AccountInfo>) {
    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?.toString();
    if (!item) {
      return;
    }
    this._itemName = item;
    this._itemId = id;
    this._itemType = ItemType.MEMBER;
    this.$.overlay.open();
  }

  _handleSavingIncludedGroups() {
    if (!this._groupName || !this._includedGroupSearchId) {
      return Promise.reject(
        new Error('group name or includedGroupSearchId undefined')
      );
    }
    return this.restApiService
      .saveIncludedGroup(
        this._groupName,
        this._includedGroupSearchId.replace(/\+/g, ' ') as GroupId,
        (errResponse, err) => {
          if (errResponse) {
            if (errResponse.status === 404) {
              fireAlert(this, SAVING_ERROR_TEXT);
              return errResponse;
            }
            throw Error(errResponse.statusText);
          }
          throw err;
        }
      )
      .then(config => {
        if (!config || !this._groupName) {
          return;
        }
        this.restApiService
          .getIncludedGroup(this._groupName)
          .then(includedGroup => {
            this._includedGroups = includedGroup;
          });
        this._includedGroupSearchName = '';
        this._includedGroupSearchId = '';
      });
  }

  _handleDeleteIncludedGroup(e: PolymerDomRepeatEvent<GroupInfo>) {
    const id = decodeURIComponent(`${e.model.get('item.id')}`).replace(
      /\+/g,
      ' '
    ) as GroupId;
    const name = e.model.get('item.name');
    const item = name || id;
    if (!item) {
      return;
    }
    this._itemName = item;
    this._itemId = id;
    this._itemType = ItemType.INCLUDED_GROUP;
    this.$.overlay.open();
  }

  _getAccountSuggestions(input: string) {
    if (input.length === 0) {
      return Promise.resolve([]);
    }
    return this.restApiService
      .getSuggestedAccounts(input, SUGGESTIONS_LIMIT)
      .then(accounts => {
        if (!accounts) return [];
        const accountSuggestions = [];
        for (const account of accounts) {
          let nameAndEmail;
          if (account.email !== undefined) {
            nameAndEmail = `${account.name} <${account.email}>`;
          } else {
            nameAndEmail = account.name;
          }
          accountSuggestions.push({
            name: nameAndEmail,
            value: account._account_id?.toString(),
          });
        }
        return accountSuggestions;
      });
  }

  _getGroupSuggestions(input: string) {
    return this.restApiService.getSuggestedGroups(input).then(response => {
      const groups: AutocompleteSuggestion[] = [];
      for (const [name, group] of Object.entries(response ?? {})) {
        groups.push({name, value: decodeURIComponent(group.id)});
      }
      return groups;
    });
  }

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

declare global {
  interface HTMLElementTagNameMap {
    'gr-group-members': GrGroupMembers;
  }
}
