import { Component, OnInit, Inject, ViewChild, OnDestroy } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { KEY_LOGIN_RES_INFO, KEY_VER_INFO, KEY_AUTH_INFO } from '@app/types';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';

import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
import * as ChatStore from '@app/store/messenger/chat';
import * as SyncStore from '@app/store/messenger/sync';
import * as AuthenticationStore from '@app/store/account/authentication';

import { UserInfo, GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import {
  UserInfoSS,
  UserInfoF,
  UserInfoDN,
  AuthResponse
} from '@ucap-webmessenger/protocol-query';
import {
  DialogService,
  ConfirmDialogComponent,
  ConfirmDialogData,
  ConfirmDialogResult,
  SnackBarService,
  AlertDialogComponent,
  AlertDialogResult,
  AlertDialogData
} from '@ucap-webmessenger/ui';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { map, take, finalize, catchError, tap } from 'rxjs/operators';
import { Subscription, of } from 'rxjs';
import {
  SelectGroupDialogComponent,
  SelectGroupDialogData,
  SelectGroupDialogResult
} from '../group/select-group.dialog.component';
import { FileUploadItem } from '@ucap-webmessenger/api';
import { CommonApiService } from '@ucap-webmessenger/api-common';
import { OpenProfileOptions } from '@ucap-webmessenger/protocol-buddy';
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
import { StatusCode } from '@ucap-webmessenger/api';
import {
  MessageWriteDialogComponent,
  MessageWriteDialogResult,
  MessageWriteDialogData
} from '../message/message-write.dialog.component';
import {
  CallService,
  PromptMessageStatusCode
} from '@ucap-webmessenger/api-prompt';
import { NGXLogger } from 'ngx-logger';
import { SmsUtils } from '@ucap-webmessenger/daesang';
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
import { environment } from '../../../../../environments/environment';
import { TranslateService } from '@ngx-translate/core';
import { UserInfoUpdateType } from '@ucap-webmessenger/protocol-info';

export interface ProfileDialogData {
  userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
  openProfileOptions?: OpenProfileOptions;
}

export interface ProfileDialogResult {
  closeEvent?: string;
}

@Component({
  selector: 'app-profile.dialog',
  templateUrl: './profile.dialog.component.html',
  styleUrls: ['./profile.dialog.component.scss']
})
export class ProfileDialogComponent implements OnInit, OnDestroy {
  userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
  loginRes: LoginResponse;
  loginResSubscription: Subscription;
  sessionVerinfo: VersionInfo2Response;
  environmentsInfo: EnvironmentsInfo;
  authInfo: AuthResponse;

  isMe: boolean;
  isBuddy: boolean;
  isFavorit: boolean;
  editableProfileImage: boolean;
  useBuddyToggleButton: boolean;

  selectAllBuddy2Subscription: Subscription;
  myDeptUserListSubscription: Subscription;

  constructor(
    public dialogRef: MatDialogRef<ProfileDialogData, ProfileDialogResult>,
    @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
    @Inject(MAT_DIALOG_DATA) public data: ProfileDialogData,
    private dialogService: DialogService,
    private sessionStorageService: SessionStorageService,
    private commonApiService: CommonApiService,
    private callService: CallService,
    private snackBarService: SnackBarService,
    private translateService: TranslateService,
    private store: Store<any>,
    private logger: NGXLogger
  ) {
    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);

    this.userInfo = data.userInfo;

    this.editableProfileImage =
      environment.productConfig.CommonSetting.editableProfileImage;
  }

  ngOnInit() {
    this.loginResSubscription = this.store
      .pipe(
        select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
        tap(loginRes => {
          if (!loginRes) {
            this.onClose();
          }

          this.loginRes = loginRes;
          if (!!loginRes && loginRes.userSeq === this.data.userInfo.seq) {
            this.isMe = true;
            this.userInfo = {
              ...this.userInfo,
              intro: loginRes.userInfo.intro
            };
          } else {
            this.isMe = false;
          }
        })
      )
      .subscribe();

    this.selectAllBuddy2Subscription = this.store
      .pipe(
        select(AppStore.MessengerSelector.SyncSelector.selectAllBuddy2),
        map(buddyList => {
          const users = buddyList.filter(
            buddy => buddy.seq === this.data.userInfo.seq
          );
          this.isBuddy = users.length > 0;
          if (this.isBuddy) {
            this.isFavorit = users[0].isFavorit;
          }
        })
      )
      .subscribe();

    if (!!this.data.openProfileOptions) {
      this.useBuddyToggleButton = !!this.data.openProfileOptions.useBuddyButton;
    } else {
      this.getCheckMyDeptUser();
    }
  }

  ngOnDestroy(): void {
    if (!!this.selectAllBuddy2Subscription) {
      this.selectAllBuddy2Subscription.unsubscribe();
    }
    if (!!this.myDeptUserListSubscription) {
      this.myDeptUserListSubscription.unsubscribe();
    }
    if (!!this.loginResSubscription) {
      this.loginResSubscription.unsubscribe();
    }
  }

  getCheckMyDeptUser() {
    this.myDeptUserListSubscription = this.store
      .pipe(
        select(
          AppStore.MessengerSelector.QuerySelector.myDepartmentUserInfoList
        ),
        map(myDeptUserList => {
          const users = myDeptUserList.filter(
            buddy => buddy.seq === this.data.userInfo.seq
          );
          this.useBuddyToggleButton = users.length === 0;
        })
      )
      .subscribe();
  }

  onClickChat(userInfo: UserInfoSS) {
    if (userInfo.seq === this.loginRes.userSeq) {
      this.store.dispatch(
        ChatStore.openRoom({ userSeqList: [this.loginRes.talkWithMeBotSeq] })
      );
    } else {
      this.store.dispatch(ChatStore.openRoom({ userSeqList: [userInfo.seq] }));
    }

    this.dialogRef.close({ closeEvent: 'CHAT' });
  }

  onClickSendMessage(userInfo: UserInfoSS) {
    if (userInfo.seq !== this.loginRes.userSeq) {
      this.dialogRef.close();

      this.dialogService.open<
        MessageWriteDialogComponent,
        MessageWriteDialogData,
        MessageWriteDialogResult
      >(MessageWriteDialogComponent, {
        width: '600px',
        height: '600px',
        disableClose: true,
        hasBackdrop: false,
        data: {
          loginRes: this.loginRes,
          environmentsInfo: this.environmentsInfo,
          receiverList: [userInfo]
        }
      });
    }
  }

  async onClickSendClickToCall(calleeNumber: string) {
    const madn = this.loginRes.madn;
    if (!madn || madn.trim().length === 0) {
      this.dialogService.open<
        AlertDialogComponent,
        AlertDialogData,
        AlertDialogResult
      >(AlertDialogComponent, {
        data: {
          title: this.translateService.instant('call.errors.label'),
          html: this.translateService.instant('call.errors.cannotCallToUser')
        }
      });

      return false;
    }

    calleeNumber = calleeNumber.replace(/\D/g, '');

    if (!!calleeNumber && calleeNumber.length > 0) {
      const result = await this.dialogService.open<
        ConfirmDialogComponent,
        ConfirmDialogData,
        ConfirmDialogResult
      >(ConfirmDialogComponent, {
        width: '360px',
        data: {
          title: this.translateService.instant('call.callTo'),
          html: this.translateService.instant('call.callWithNumber', {
            phoneNumber: calleeNumber
          })
        }
      });

      if (!!result && !!result.choice && result.choice) {
        this.callService
          .sendCall({
            userSeq: this.loginRes.userSeq,
            deviceType: this.environmentsInfo.deviceType,
            tokenKey: this.loginRes.tokenString,
            calleeNumber
          })
          .pipe(
            take(1),
            map(res => {
              if (res.responseCode === PromptMessageStatusCode.Success) {
                this.logger.debug('SUCCESS');
                this.logger.debug(res);
              } else {
                this.logger.error(res);
              }
            }),
            catchError(error => of(this.logger.debug(error)))
          )
          .subscribe();
      }
    } else {
      this.dialogService.open<
        AlertDialogComponent,
        AlertDialogData,
        AlertDialogResult
      >(AlertDialogComponent, {
        data: {
          title: this.translateService.instant('call.errors.label'),
          html: this.translateService.instant(
            'call.errors.cannotCallToUserWithoutPhomeNumber'
          )
        }
      });
    }
  }

  onClickSendSms(calleeNumber: string) {
    const smsUtil = new SmsUtils(
      this.sessionStorageService,
      this.nativeService
    );
    if (!smsUtil.getAuthSms()) {
      this.dialogService.open<
        AlertDialogComponent,
        AlertDialogData,
        AlertDialogResult
      >(AlertDialogComponent, {
        data: {
          title: this.translateService.instant('sms.errors.label'),
          html: this.translateService.instant('sms.errors.haveNoPermission')
        }
      });
      return false;
    }

    calleeNumber = calleeNumber.replace(/\D/g, '');
    smsUtil.openSendSms(this.loginRes.tokenString, [calleeNumber]);
    // if (!!calleeNumber && calleeNumber.length > 0) {
    //   smsUtil.openSendSms(this.loginRes.tokenString, [calleeNumber]);
    // } else {
    //   // this.dialogService.open<
    //   //   AlertDialogComponent,
    //   //   AlertDialogData,
    //   //   AlertDialogResult
    //   // >(AlertDialogComponent, {
    //   //   data: {
    //   //     title: '',
    //   //     html: `상대방 번호가 없어 전화를 걸 수 없습니다.`
    //   //   }
    //   // });
    // }
  }

  onClickToggleFavorit(param: { userInfo: UserInfoSS; isFavorit: boolean }) {
    this.store.dispatch(
      SyncStore.updateBuddy({
        seq: param.userInfo.seq,
        isFavorit: param.isFavorit
      })
    );
  }

  async onClickToggleBuddy(param: { userInfo: UserInfoSS; isBuddy: boolean }) {
    if (param.isBuddy) {
      // 동료추가.
      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));
          trgtUserSeq.push(param.userInfo.seq);

          this.store.dispatch(
            SyncStore.updateGroupMember({
              oldGroup,
              trgtUserSeq
            })
          );
        }
      }
    } else {
      // 동료삭제.
      const result = await this.dialogService.open<
        ConfirmDialogComponent,
        ConfirmDialogData,
        ConfirmDialogResult
      >(ConfirmDialogComponent, {
        width: '360px',
        data: {
          title: this.translateService.instant('group.removeBuddyFromGroup'),
          html: this.translateService.instant(
            'group.confirmRemoveBuddyFromGroup',
            { target: `${param.userInfo.name} ${param.userInfo.grade}` }
          )
        }
      });

      if (!!result && !!result.choice && result.choice) {
        this.store.dispatch(
          SyncStore.delBuddyAndClear({ seq: param.userInfo.seq })
        );
        this.isBuddy = false;

        this.getCheckMyDeptUser();
      }
    }
  }

  onUploadProfileImage(profileImageFileUploadItem: FileUploadItem) {
    this.commonApiService
      .fileProfileSave(
        {
          userSeq: this.loginRes.userSeq,
          deviceType: this.environmentsInfo.deviceType,
          token: this.loginRes.tokenString,
          file: profileImageFileUploadItem.file,
          fileUploadItem: profileImageFileUploadItem
        },
        this.sessionVerinfo.profileUploadUrl
      )
      .pipe(
        take(1),
        map(res => {
          if (!res) {
            return;
          }
          if (StatusCode.Success === res.statusCode) {
            return res;
          } else {
            throw res;
          }
        }),
        finalize(() => {
          setTimeout(() => {
            profileImageFileUploadItem.uploadingProgress$ = undefined;
          }, 1000);
        })
      )
      .subscribe(
        res => {
          const userInfo = {
            ...this.loginRes.userInfo,
            profileImageFile: res.profileSubDir
          };

          this.store.dispatch(
            AuthenticationStore.updateLoginRes({
              loginRes: {
                ...this.loginRes,
                userInfo
              }
            })
          );
          this.userInfo = userInfo as any;
        },
        error => {
          this.snackBarService.open(
            this.translateService.instant(
              'profile.errors.failToChangeProfileImage'
            ),
            '',
            {
              duration: 3000,
              verticalPosition: 'bottom'
            }
          );
        }
      );
  }

  onUpdateIntro(intro: string) {
    this.store.dispatch(
      AuthenticationStore.infoUser({
        req: {
          type: UserInfoUpdateType.Intro,
          info: intro
        }
      })
    );
  }

  onClose() {
    this.dialogRef.close();
  }
}
