import {
  Component,
  OnInit,
  OnDestroy,
  Output,
  EventEmitter,
  Input,
  ViewChild,
  AfterViewChecked,
  ChangeDetectorRef
} from '@angular/core';
import { ucapAnimations, DialogService } from '@ucap-webmessenger/ui';
import { Observable, Subscription, of } from 'rxjs';
import {
  DeptInfo,
  QueryProtocolService,
  DeptSearchType,
  UserInfoSS,
  DeptUserResponse,
  UserInfoF,
  UserInfoDN,
  SSVC_TYPE_QUERY_DEPT_USER_DATA,
  SSVC_TYPE_QUERY_DEPT_USER_RES,
  DeptUserData,
  AuthResponse
} from '@ucap-webmessenger/protocol-query';
import { UserInfo, GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger';

import * as AppStore from '@app/store';
import * as QueryStore from '@app/store/messenger/query';
import * as SyncStore from '@app/store/messenger/sync';
import * as ChatStore from '@app/store/messenger/chat';
import * as StatusStore from '@app/store/messenger/status';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import {
  LoginInfo,
  KEY_LOGIN_INFO,
  KEY_VER_INFO,
  EnvironmentsInfo,
  KEY_ENVIRONMENTS_INFO,
  KEY_AUTH_INFO
} from '@app/types';
import { take, map, tap, delay, catchError } from 'rxjs/operators';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { Company } from '@ucap-webmessenger/api-external';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { MatMenuTrigger } from '@angular/material';
import {
  MessageWriteDialogComponent,
  MessageWriteDialogResult,
  MessageWriteDialogData
} from '../../dialogs/message/message-write.dialog.component';
import {
  SelectGroupDialogComponent,
  SelectGroupDialogResult,
  SelectGroupDialogData
} from '../../dialogs/group/select-group.dialog.component';
import {
  SelectedUserListDialogComponent,
  SelectedUserListDialogResult,
  SelectedUserListDialogData
} from '../../dialogs/organization/selected-user-list.dialog.component';
import { TranslateService } from '@ngx-translate/core';
import { StringFormatterPhonePipe } from 'projects/ucap-webmessenger-ui/src/lib/pipes/string.pipe';
import { VirtualScrollerComponent } from 'ngx-virtual-scroller';
import { OrganizationService } from '@ucap-webmessenger/ui-organization';

@Component({
  selector: 'app-layout-chat-left-sidenav-organization',
  templateUrl: './organization.component.html',
  styleUrls: ['./organization.component.scss'],
  animations: ucapAnimations
})
export class OrganizationComponent
  implements OnInit, OnDestroy, AfterViewChecked {
  @ViewChild('orgUserContextMenuTrigger', { static: true })
  orgUserContextMenuTrigger: MatMenuTrigger;
  orgUserContextMenuPosition = { x: '0px', y: '0px' };

  @Input()
  showTitle = true;
  @Input()
  /** 사용자 선택용으로 사용시 true 로 유입 */
  isUserSelect = false;
  @Input()
  /** 선택된 사용자의 리스트 */
  selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
  @Input()
  /** 선택할 수 없는 사용자 리스트 */
  ignoreUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
  @Input()
  isVisible = true;

  @Output()
  checkUser = new EventEmitter<{
    isChecked: boolean;
    userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
  }>();
  @Output()
  toggleUser = new EventEmitter<
    UserInfo | UserInfoSS | UserInfoF | UserInfoDN
  >();
  @Output()
  checkAllUser = new EventEmitter<{
    isChecked: boolean;
    userInfos: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[];
  }>();
  @Output()
  resetSelectedUserList = new EventEmitter<
    (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[]
  >();
  @Output()
  openProfile = new EventEmitter<{ userSeq: number }>();
  @Output()
  sendCall = new EventEmitter<string>();
  @Output()
  sendSms = new EventEmitter<string>();

  @ViewChild('vsDeptUser', { static: false })
  private vsDeptUser: VirtualScrollerComponent;

  @ViewChild('vsDeptSearchUser', { static: false })
  private vsDeptSearchUser: VirtualScrollerComponent;

  @ViewChild(PerfectScrollbarDirective, { static: false })
  psDirectiveRef?: PerfectScrollbarDirective;

  companyList$: Observable<Company[]>;
  companyCode: string;

  departmentInfoList$: Observable<DeptInfo[]>;
  selectedDepartmentUserInfoList: UserInfoSS[];
  selectedDepartmentProcessing = false;
  selectedDepartmentName: {
    name: string;
    nameEn: string;
    nameCn: string;
  };

  myDepartmentUserInfoList: UserInfoSS[] = [];
  myDepartmentUserInfoListSubscription: Subscription;

  loginInfo: LoginInfo;
  loginRes: LoginResponse;
  sessionVerinfo: VersionInfo2Response;
  environmentsInfo: EnvironmentsInfo;
  authInfo: AuthResponse;

  isShowSearch = false;
  searchUserInfos: UserInfoSS[] = [];

  /** 부서원 리스트에 virture scroll의 size 가 체킹되지 않아 강제 수행. 1번만. */
  isInitList = false;

  constructor(
    private store: Store<any>,
    private sessionStorageService: SessionStorageService,
    private queryProtocolService: QueryProtocolService,
    private organizationService: OrganizationService,
    private dialogService: DialogService,
    private translateService: TranslateService,
    private changeDetectorRef: ChangeDetectorRef,
    private logger: NGXLogger
  ) {
    this.loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO);
    this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
      KEY_VER_INFO
    );
    this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
      KEY_ENVIRONMENTS_INFO
    );
    this.authInfo = this.sessionStorageService.get<AuthResponse>(KEY_AUTH_INFO);
  }

  ngOnInit() {
    this.companyCode = this.loginInfo.companyCode;
    this.companyList$ = this.store.pipe(
      select(AppStore.SettingSelector.CompanySelector.companyList)
    );

    this.departmentInfoList$ = this.store.pipe(
      select(AppStore.MessengerSelector.QuerySelector.departmentInfoList)
    );

    this.myDepartmentUserInfoListSubscription = this.store
      .pipe(
        select(
          AppStore.MessengerSelector.QuerySelector.myDepartmentUserInfoList
        )
      )
      .subscribe(list => {
        this.myDepartmentUserInfoList = list;
        if (!this.selectedDepartmentUserInfoList) {
          this.selectedDepartmentUserInfoList = list;
        }

        if (!!this.vsDeptUser) {
          this.vsDeptUser.scrollToIndex(0, true, 0, 0);
        }
        if (!!this.psDirectiveRef) {
          this.psDirectiveRef.update();
        }
      });

    this.store
      .pipe(
        take(1),
        select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
        map(loginRes => {
          this.store.dispatch(
            QueryStore.myDeptUser({
              divCd: 'ORG',
              companyCode: this.loginInfo.companyCode,
              seq: loginRes.departmentCode,
              search: '',
              searchRange: DeptSearchType.All,
              senderCompanyCode: this.loginInfo.companyCode,
              senderEmployeeType: loginRes.userInfo.employeeType
            })
          );
          return loginRes;
        }),
        map(loginRes => {
          this.loginRes = loginRes;
          this.selectedDepartmentName = {
            name: loginRes.userInfo.deptName,
            nameEn: loginRes.userInfo.deptNameEn,
            nameCn: loginRes.userInfo.deptNameCn
          };
        })
      )
      .subscribe();
  }

  ngAfterViewChecked(): void {
    if (
      !!this.vsDeptUser &&
      !!this.selectedDepartmentUserInfoList &&
      this.selectedDepartmentUserInfoList.length > 0 &&
      !this.isInitList &&
      this.isVisible
    ) {
      this.isInitList = true;
    }
  }

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

  /** 유저검색 */
  onKeyDownEnterOrganizationTenantSearch(params: {
    companyCode: string;
    searchWord: string;
  }) {
    if (params.searchWord.trim().length > 1) {
      this.isShowSearch = true;
      this.selectedDepartmentProcessing = true;

      this.organizationService
        .getDeptUser({
          divCd: 'GRP',
          companyCode: params.companyCode,
          searchRange: DeptSearchType.All,
          search: params.searchWord,
          senderCompanyCode: params.companyCode,
          senderEmployeeType: this.loginRes.userInfo.employeeType
        })
        .pipe(take(1))
        .subscribe(
          datas => {
            this.searchUserInfos = datas.userInfos;
            this.selectedDepartmentProcessing = false;

            if (!!this.vsDeptSearchUser) {
              this.vsDeptSearchUser.scrollToIndex(0);
            }
            if (!!this.psDirectiveRef) {
              this.psDirectiveRef.update();
            }
          },
          error => {
            this.logger.error(error);
          },
          () => {
            this.selectedDepartmentProcessing = false;
          }
        );

      // const searchUserInfos: UserInfoSS[] = [];
      // this.queryProtocolService
      //   .deptUser({
      //     divCd: 'GRP',
      //     companyCode: params.companyCode,
      //     searchRange: DeptSearchType.All,
      //     search: params.searchWord,
      //     senderCompanyCode: params.companyCode,
      //     senderEmployeeType: this.loginRes.userInfo.employeeType
      //   })
      //   .pipe(
      //     map(res => {
      //       switch (res.SSVC_TYPE) {
      //         case SSVC_TYPE_QUERY_DEPT_USER_DATA:
      //           const userInfos = (res as DeptUserData).userInfos;
      //           // searchUserInfos.push(
      //           //   ...userInfos.filter(
      //           //     userInfo => userInfo.seq !== this.loginRes.userSeq
      //           //   )
      //           // );
      //           searchUserInfos.push(...userInfos);
      //           break;
      //         case SSVC_TYPE_QUERY_DEPT_USER_RES:
      //           {
      //             // 검색 결과 처리.
      //             this.searchUserInfos = searchUserInfos;
      //             this.selectedDepartmentProcessing = false;

      //             if (!!this.vsDeptSearchUser) {
      //               this.vsDeptSearchUser.scrollToIndex(0);
      //             }
      //             if (!!this.psDirectiveRef) {
      //               this.psDirectiveRef.update();
      //             }
      //           }
      //           break;
      //       }
      //     }),
      //     catchError(error => {
      //       this.selectedDepartmentProcessing = false;
      //       return of(this.logger.error(error));
      //     })
      //   )
      //   .subscribe();
    }
  }
  /** 검색 취소 */
  onClickCancel() {
    this.isShowSearch = false;
    this.searchUserInfos = [];
  }

  onSelectedOrganization(deptInfo: DeptInfo) {
    this.onClickCancel();

    this.selectedDepartmentName = deptInfo;
    this.selectedDepartmentProcessing = true;
    this.store
      .pipe(
        take(1),
        select(AppStore.AccountSelector.AuthenticationSelector.loginRes)
      )
      .subscribe(loginRes => {
        this.organizationService
          .getDeptUser({
            divCd: 'ORG',
            companyCode: this.loginInfo.companyCode,
            seq: deptInfo.seq,
            search: '',
            searchRange: DeptSearchType.All,
            senderCompanyCode: this.loginInfo.companyCode,
            senderEmployeeType: loginRes.userInfo.employeeType
          })
          .pipe(take(1))
          .subscribe(
            datas => {
              // this.logger.debug('onSelectedOrganization', datas);
              this.selectedDepartmentUserInfoList = datas.userInfos;

              if (!!this.vsDeptUser) {
                this.vsDeptUser.scrollToIndex(0, true, 0, 0);
              }
              if (!!this.psDirectiveRef) {
                this.psDirectiveRef.update();
              }
            },
            error => {
              this.logger.error(error);
            },
            () => {
              this.selectedDepartmentProcessing = false;
            }
          );
      });

    // this.store
    //   .pipe(
    //     take(1),
    //     select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
    //     map(loginRes => {
    //       this.store.dispatch(
    //         QueryStore.deptUser({
    //           divCd: 'ORG',
    //           companyCode: this.loginInfo.companyCode,
    //           seq: deptInfo.seq,
    //           search: '',
    //           searchRange: DeptSearchType.All,
    //           senderCompanyCode: this.loginInfo.companyCode,
    //           senderEmployeeType: loginRes.userInfo.employeeType
    //         })
    //       );
    //     }),
    //     map(() => {
    //       this.selectedDepartmentName = deptInfo;
    //     })
    //   )
    //   .subscribe();
  }

  /** 전체 체크여부 */
  getCheckedAllUser() {
    const compareList: UserInfoSS[] = this.isShowSearch
      ? this.searchUserInfos
      : this.selectedDepartmentUserInfoList;

    if (
      !compareList ||
      compareList.length === 0 ||
      compareList
        .filter(item => item.seq !== this.loginRes.userSeq)
        .filter(
          item =>
            !(
              this.selectedUserList.filter(user => user.seq === item.seq)
                .length > 0
            )
        ).length > 0
    ) {
      return false;
    } else {
      return true;
    }
  }
  /** ignoreUserList(선택 무시할 인원) 이 있을 경우 판단하여 checkable 판단. */
  getCheckableUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
    if (
      !!this.ignoreUserList &&
      this.ignoreUserList.filter(user => user.seq === userInfo.seq).length > 0
    ) {
      return false;
    }

    return true;
  }
  /** 리스트 checkable 할 경우 checkbox 의 isChecked 를 관장하며 리스트의 전체선택 여부를 판단한다. */
  getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      return (
        this.selectedUserList.filter(item => item.seq === userInfo.seq).length >
        0
      );
    }
    return false;
  }

  /** 전체선택 이벤트 */
  onCheckAllUser(value: boolean) {
    this.checkAllUser.emit({
      isChecked: value,
      userInfos: (this.isShowSearch
        ? this.searchUserInfos
        : this.selectedDepartmentUserInfoList
      ).filter(user => user.seq !== this.loginRes.userSeq)
    });

    this.changeDetectorRef.detectChanges();
  }

  /** 리스트가 checkable 할 경우 checkbox 의 change 이벤트를 상위 컴포넌트로 전달한다. */
  onCheckUser(params: {
    isChecked: boolean;
    userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
  }) {
    this.checkUser.emit(params);
  }
  onToggleUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
    if (userInfo.seq === this.loginRes.userSeq) {
      return;
    }
    this.toggleUser.emit(userInfo);
  }

  onClickOpenProfile(userSeq: number) {
    this.openProfile.emit({ userSeq });
  }
  onClickSendClickToCall(calleeNumber: string) {
    this.sendCall.emit(calleeNumber);
  }

  async onClickShowSelectedUserList() {
    this.logger.debug('onClickShowSelectedUserList', this.selectedUserList);

    const result = await this.dialogService.open<
      SelectedUserListDialogComponent,
      SelectedUserListDialogData,
      SelectedUserListDialogResult
    >(SelectedUserListDialogComponent, {
      data: {
        title: this.translateService.instant('organization.selectedUser'),
        selectedUserList: this.selectedUserList
      }
    });

    if (!!result && !!result.choice && result.choice) {
      if (!!result.selectedUserList) {
        this.resetSelectedUserList.emit(result.selectedUserList);
      }
    }
  }

  async onClickAddGroup() {
    this.logger.debug('onClickAddGroup', this.selectedUserList);

    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.selectedUserList
          .filter(v => result.group.userSeqs.indexOf(v.seq) < 0)
          .forEach(user => {
            trgtUserSeq.push(user.seq);
          });

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

        // 상위 컴포넌트의 selectedUserList clear.
        this.checkAllUser.emit({
          isChecked: false,
          userInfos: this.selectedUserList
        });
      }
    }
  }
  onClickChatOpen() {
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      const seq: number[] = [];
      this.selectedUserList.map(user => seq.push(user.seq));
      this.store.dispatch(ChatStore.openRoom({ userSeqList: seq }));

      // 상위 컴포넌트의 selectedUserList clear.
      this.checkAllUser.emit({
        isChecked: false,
        userInfos: this.selectedUserList
      });
    }
  }
  onClickConference() {
    this.logger.debug('onClickConference', this.selectedUserList);

    // 상위 컴포넌트의 selectedUserList clear.
    this.checkAllUser.emit({
      isChecked: false,
      userInfos: this.selectedUserList
    });
  }

  onContextMenuOrgUser(
    event: MouseEvent,
    userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN
  ) {
    event.preventDefault();
    event.stopPropagation();

    this.orgUserContextMenuPosition.x = event.clientX + 'px';
    this.orgUserContextMenuPosition.y = event.clientY + 'px';
    this.orgUserContextMenuTrigger.menu.focusFirstItem('mouse');
    this.orgUserContextMenuTrigger.menuData = { userInfo };
    this.orgUserContextMenuTrigger.openMenu();
  }

  getEnableCall(): boolean {
    if (
      !!this.loginRes &&
      !!this.loginRes.madn &&
      this.loginRes.madn.trim().length > 0
    ) {
      return false;
    } else {
      return true;
    }
  }
  getShowCall(type: string, userInfo: UserInfo) {
    let valid = false;
    switch (type) {
      case 'CALL_LINE':
        {
          if (
            !!userInfo &&
            !!userInfo.lineNumber &&
            userInfo.lineNumber.trim().length > 0
          ) {
            valid = true;
          }
        }
        break;
      case 'CALL_MOBILE':
        {
          if (
            !!userInfo &&
            !!userInfo.hpNumber &&
            userInfo.hpNumber.trim().length > 0
          ) {
            valid = true;
          }
        }
        break;
    }

    return valid;
  }
  async onClickContextMenu(type: string, userInfo: UserInfo) {
    switch (type) {
      case 'CALL_LINE':
        {
          this.onClickSendClickToCall(userInfo.lineNumber);
        }
        break;
      case 'CALL_MOBILE':
        {
          this.onClickSendClickToCall(userInfo.hpNumber);
        }
        break;
      case 'SEND_MESSAGE':
        {
          this.dialogService.open<
            MessageWriteDialogComponent,
            MessageWriteDialogData,
            MessageWriteDialogResult
          >(MessageWriteDialogComponent, {
            width: '600px',
            height: '600px',
            disableClose: true,
            hasBackdrop: false,
            data: {
              loginRes: this.loginRes,
              environmentsInfo: this.environmentsInfo,
              receiverList: [userInfo]
            }
          });
        }
        break;
      case 'SEND_SMS':
        {
          this.sendSms.emit(userInfo.hpNumber);
        }
        break;
    }
  }

  getTooltip(userInfo: UserInfoSS): string {
    return `${
      userInfo.companyName
    } / ${new StringFormatterPhonePipe().transform(
      userInfo.lineNumber
    )} / ${new StringFormatterPhonePipe().transform(userInfo.hpNumber)}`;
  }
}
