import React from 'react';

import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
import { SessionIdEditable } from './SessionIdEditable';
import { UserSearchDropdown } from './UserSearchDropdown';
import { ContactType, SessionMemberListItem } from './SessionMemberListItem';
import { ConversationType } from '../../state/ducks/conversations';
import {
  SessionButton,
  SessionButtonColor,
  SessionButtonType,
} from './SessionButton';
import { SessionSpinner } from './SessionSpinner';
import { SessionGroupType } from './LeftPaneChannelSection';

interface Props {
  overlayMode: 'message' | 'contact' | SessionGroupType;
  onChangeSessionID: any;
  onCloseClick: any;
  onButtonClick: any;
  contacts?: Array<ConversationType>;
  searchTerm?: string;
  searchResults?: any;
  updateSearch?: any;
  showSpinner?: boolean;
}

interface State {
  groupName: string;
  selectedMembers: Array<ContactType>;
}

export class SessionClosableOverlay extends React.Component<Props, State> {
  private readonly inputRef: React.RefObject<SessionIdEditable>;

  public constructor(props: Props) {
    super(props);

    this.state = {
      groupName: '',
      selectedMembers: [],
    };

    this.inputRef = React.createRef();
    this.onGroupNameChanged = this.onGroupNameChanged.bind(this);
  }

  public componentDidMount() {
    if (this.inputRef.current) {
      this.inputRef.current.focus();
    }
  }

  public getContacts() {
    const conversations = window.getConversations();

    let conversationList = conversations;
    if (conversationList !== undefined) {
      conversationList = conversationList.filter((conv: any) => {
        return !conv.isRss() && !conv.isPublic() && conv.attributes.lastMessage;
      });
    }

    const friends = conversationList.map((d: any) => {
      const lokiProfile = d.getLokiProfile();
      const name = lokiProfile ? lokiProfile.displayName : 'Anonymous';

      // TODO: should take existing members into account
      const existingMember = false;

      return {
        id: d.id,
        authorPhoneNumber: d.id,
        authorProfileName: name,
        selected: false,
        authorName: name,
        authorColor: d.getColor(),
        checkmarked: false,
        existingMember,
      };
    });

    return friends;
  }

  // tslint:disable-next-line max-func-body-length */
  public render(): JSX.Element {
    const {
      overlayMode,
      onCloseClick,
      onChangeSessionID,
      showSpinner,
      searchTerm,
      updateSearch,
      searchResults,
      onButtonClick,
    } = this.props;

    const isAddContactView = overlayMode === 'contact';
    const isMessageView = overlayMode === 'message';

    const isOpenGroupView = overlayMode === SessionGroupType.Open;
    const isClosedGroupView = overlayMode === SessionGroupType.Closed;

    let title;
    let buttonText;
    let descriptionLong;
    let subtitle;
    let placeholder;
    switch (overlayMode) {
      case 'message':
        title = window.i18n('newSession');
        buttonText = window.i18n('next');
        descriptionLong = window.i18n('usersCanShareTheir...');
        subtitle = window.i18n('enterSessionID');
        placeholder = window.i18n('pasteSessionIDRecipient');
        break;
      case 'contact':
        title = window.i18n('addContact');
        buttonText = window.i18n('next');
        descriptionLong = window.i18n('usersCanShareTheir...');
        subtitle = window.i18n('enterSessionID');
        placeholder = window.i18n('pasteSessionIDRecipient');
        break;
      case 'open-group':
        title = window.i18n('addChannel');
        buttonText = window.i18n('joinChannel');
        descriptionLong = window.i18n('addChannelDescription');
        subtitle = window.i18n('enterChannelURL');
        placeholder = window.i18n('channelUrlPlaceholder');
        break;
      case 'closed-group':
        title = window.i18n('newClosedGroup');
        buttonText = window.i18n('createClosedGroup');
        descriptionLong = window.i18n('createClosedGroupDescription');
        subtitle = window.i18n('createClosedGroupNamePrompt');
        placeholder = window.i18n('createClosedGroupPlaceholder');
        break;
      default:
        break;
    }

    const { groupName, selectedMembers } = this.state;
    const ourSessionID = window.textsecure.storage.user.getNumber();

    const contacts = this.getContacts();
    const noContactsForClosedGroup =
      overlayMode === SessionGroupType.Closed && contacts.length === 0;

    return (
      <div className="module-left-pane-overlay">
        <div className="exit">
          <SessionIconButton
            iconSize={SessionIconSize.Small}
            iconType={SessionIconType.Exit}
            onClick={onCloseClick}
          />
        </div>

        <div className="spacer-md" />

        <h2>{title}</h2>

        <h3>
          {subtitle}
          <hr className="green-border" />
        </h3>
        <hr className="white-border" />

        {isOpenGroupView || isClosedGroupView ? (
          <div className="create-group-name-input">
            <SessionIdEditable
              ref={this.inputRef}
              editable={!noContactsForClosedGroup}
              placeholder={placeholder}
              value={this.state.groupName}
              maxLength={window.CONSTANTS.MAX_GROUPNAME_LENGTH}
              onChange={this.onGroupNameChanged}
            />

            {/*  */}
          </div>
        ) : (
          <SessionIdEditable
            ref={this.inputRef}
            editable={true}
            placeholder={placeholder}
            onChange={onChangeSessionID}
          />
        )}

        {showSpinner && <SessionSpinner />}

        {isClosedGroupView && (
          <>
            <div className="spacer-lg" />

            <div className="group-member-list__container">
              {noContactsForClosedGroup ? (
                <div className="group-member-list__no-contacts">
                  {window.i18n('noContactsForGroup')}
                </div>
              ) : (
                <div className="group-member-list__selection">
                  {this.renderMemberList()}
                </div>
              )}
            </div>

            <div className="spacer-lg" />
          </>
        )}

        <div className="session-description-long">{descriptionLong}</div>
        {isMessageView && <h4>{window.i18n('or')}</h4>}

        {isMessageView && (
          <UserSearchDropdown
            searchTerm={searchTerm || ''}
            updateSearch={updateSearch}
            placeholder={window.i18n('searchByIDOrDisplayName')}
            searchResults={searchResults}
          />
        )}

        {isAddContactView && (
          <div className="panel-text-divider">
            <span>{window.i18n('yourPublicKey')}</span>
          </div>
        )}

        {isAddContactView && (
          <SessionIdEditable
            editable={false}
            placeholder=""
            text={ourSessionID}
          />
        )}

        <SessionButton
          buttonColor={SessionButtonColor.Green}
          buttonType={SessionButtonType.BrandOutline}
          text={buttonText}
          disabled={noContactsForClosedGroup}
          onClick={() => onButtonClick(groupName, selectedMembers)}
        />
      </div>
    );
  }

  private renderMemberList() {
    const members = this.getContacts();

    const memberList = members.map((member: ContactType) => (
      <SessionMemberListItem
        member={member}
        isSelected={false}
        onSelect={(selectedMember: ContactType) => {
          this.handleSelectMember(selectedMember);
        }}
        onUnselect={(selectedMember: ContactType) => {
          this.handleUnselectMember(selectedMember);
        }}
      />
    ));

    return memberList;
  }

  private handleSelectMember(member: ContactType) {
    if (this.state.selectedMembers.includes(member)) {
      return;
    }

    this.setState({
      selectedMembers: [...this.state.selectedMembers, member],
    });
  }

  private handleUnselectMember(member: ContactType) {
    this.setState({
      selectedMembers: this.state.selectedMembers.filter(selectedMember => {
        return selectedMember !== member;
      }),
    });
  }

  private onGroupNameChanged(event: any) {
    this.setState({
      groupName: event,
    });
  }
}
