import {
  Component,
  OnInit,
  OnDestroy,
  Output,
  EventEmitter,
  ViewChild
} from '@angular/core';
import { Subscription } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { tap, map, take } from 'rxjs/operators';

import * as AppStore from '@app/store';
import * as SyncStore from '@app/store/messenger/sync';
import * as RoomStore from '@app/store/messenger/room';

import { UserInfo, RoomInfo, RoomType } from '@ucap-webmessenger/protocol-room';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import {
  DialogService,
  ConfirmDialogComponent,
  ConfirmDialogResult,
  ConfirmDialogData
} from '@ucap-webmessenger/ui';
import {
  SelectGroupDialogComponent,
  SelectGroupDialogResult,
  SelectGroupDialogData
} from '../../dialogs/group/select-group.dialog.component';
import { GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import {
  CreateChatDialogComponent,
  CreateChatDialogResult,
  CreateChatDialogData
} from '../../dialogs/chat/create-chat.dialog.component';
import {
  UserSelectDialogType,
  KEY_LOGIN_RES_INFO,
  KEY_VER_INFO
} from '@app/types';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { MatMenuTrigger, MatDialog } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'app-layout-chat-right-drawer-room-user-list',
  templateUrl: './room-user-list.component.html',
  styleUrls: ['./room-user-list.component.scss']
})
export class RoomUserListComponent implements OnInit, OnDestroy {
  @Output()
  openProfile = new EventEmitter<number>();

  @ViewChild('roomUserContextMenuTrigger', { static: true })
  roomUserContextMenuTrigger: MatMenuTrigger;
  roomUserContextMenuPosition = { x: '0px', y: '0px' };

  roomInfo: RoomInfo;
  roomInfoSubscription: Subscription;

  userInfoList: UserInfo[];
  userInfoListSubscription: Subscription;

  loginRes: LoginResponse;
  sessionVerinfo: VersionInfo2Response;

  constructor(
    private store: Store<any>,
    private sessionStorageService: SessionStorageService,
    private translateService: TranslateService,
    private dialogService: DialogService,
    private dialogRef: MatDialog
  ) {
    this.loginRes = this.sessionStorageService.get<LoginResponse>(
      KEY_LOGIN_RES_INFO
    );
    this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
      KEY_VER_INFO
    );
  }

  ngOnInit() {
    this.userInfoListSubscription = this.store
      .pipe(
        select(AppStore.MessengerSelector.RoomSelector.selectUserinfolist),
        tap(userInfoList => {
          this.userInfoList = userInfoList
            .filter(userInfo => userInfo.isJoinRoom === true)
            .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
        })
      )
      .subscribe();

    this.roomInfoSubscription = this.store
      .pipe(
        select(AppStore.MessengerSelector.RoomSelector.roomInfo),
        tap(roomInfo => {
          this.roomInfo = roomInfo;
          this.clearView();
        })
      )
      .subscribe();
  }

  ngOnDestroy(): void {
    if (!!this.userInfoListSubscription) {
      this.userInfoListSubscription.unsubscribe();
    }
    if (!!this.roomInfoSubscription) {
      this.roomInfoSubscription.unsubscribe();
    }
  }

  clearView() {
    if (
      !!this.roomUserContextMenuTrigger &&
      this.roomUserContextMenuTrigger.menuOpen
    ) {
      this.roomUserContextMenuTrigger.closeMenu();
    }
    this.dialogRef.closeAll();
  }

  getStatusBulkInfo(buddy: UserInfo) {
    return this.store.pipe(
      select(
        AppStore.MessengerSelector.StatusSelector.selectEntitiesStatusBulkInfo
      ),
      map(statusBulkInfo =>
        !!statusBulkInfo ? statusBulkInfo[buddy.seq] : undefined
      )
    );
  }

  onClickOpenProfile(userSeq: number) {
    this.openProfile.emit(userSeq);
  }

  async onClickAddMember() {
    const result = await this.dialogService.open<
      CreateChatDialogComponent,
      CreateChatDialogData,
      CreateChatDialogResult
    >(CreateChatDialogComponent, {
      width: '600px',
      data: {
        type: UserSelectDialogType.EditChatMember,
        title: this.translateService.instant('chat.modifyRoomMember'),
        curRoomUser: this.userInfoList.filter(
          user => user.seq !== this.loginRes.userSeq && user.isJoinRoom
        )
      }
    });

    if (!!result && !!result.choice && result.choice) {
      // include me here..
      const userSeqs: number[] = this.userInfoList
        .filter(userInfo => userInfo.isJoinRoom)
        .map(userInfo => userInfo.seq);

      if (!!result.selectedUserList && result.selectedUserList.length > 0) {
        result.selectedUserList.forEach(user => {
          if (userSeqs.indexOf(user.seq) < 0) {
            userSeqs.push(user.seq);
          }
        });
      }

      if (userSeqs.length > 0) {
        this.store.dispatch(
          RoomStore.inviteOrOpen({
            req: {
              divCd: 'Invite',
              userSeqs
            }
          })
        );
      }
    }
  }

  async onClickAddGroup() {
    const result = await this.dialogService.open<
      SelectGroupDialogComponent,
      SelectGroupDialogData,
      SelectGroupDialogResult
    >(SelectGroupDialogComponent, {
      width: '600px',
      data: {
        title: this.translateService.instant('group.selectTargetGroup')
      }
    });

    if (!!result && !!result.choice && result.choice) {
      if (!!result.group) {
        const oldGroup: GroupDetailData = result.group;
        const trgtUserSeq: number[] = [];
        result.group.userSeqs.map(seq => trgtUserSeq.push(seq));
        this.userInfoList
          .filter(v => result.group.userSeqs.indexOf(v.seq) < 0)
          .forEach(user => {
            trgtUserSeq.push(user.seq);
          });

        this.store.dispatch(
          SyncStore.updateGroupMember({
            oldGroup,
            trgtUserSeq
          })
        );
      }
    }
  }

  onContextMenuRoomUser(event: MouseEvent, buddy: UserInfo) {
    event.preventDefault();
    event.stopPropagation();

    if (this.roomInfo.roomType !== RoomType.Multi) {
      return;
    }
    if (buddy.seq === this.loginRes.userSeq) {
      return;
    }

    this.roomUserContextMenuPosition.x = event.clientX + 'px';
    this.roomUserContextMenuPosition.y = event.clientY + 'px';
    this.roomUserContextMenuTrigger.menu.focusFirstItem('mouse');
    this.roomUserContextMenuTrigger.menuData = { buddy };
    this.roomUserContextMenuTrigger.openMenu();
  }

  async onClickContextMenu(type: string, buddy: UserInfo) {
    switch (type) {
      case 'FORCING_EXIT':
        {
          const result = await this.dialogService.open<
            ConfirmDialogComponent,
            ConfirmDialogData,
            ConfirmDialogResult
          >(ConfirmDialogComponent, {
            data: {
              title: this.translateService.instant('chat.ejectFromRoom'),
              html: this.translateService.instant('chat.confirmEjectFromRoom', {
                targetMember: buddy.name
              })
            }
          });

          if (!!result && !!result.choice && result.choice) {
            this.store.dispatch(
              RoomStore.exitForcing({
                req: {
                  roomSeq: this.roomInfo.roomSeq,
                  senderSeq: this.loginRes.userSeq,
                  type: 'A',
                  userSeqs: [buddy.seq]
                }
              })
            );
          }
        }
        break;
    }
  }
}
