import {
  Component,
  OnInit,
  OnDestroy,
  Output,
  EventEmitter,
  ViewChild,
  Input,
  AfterViewChecked
} from '@angular/core';
import { Observable, Subscription, merge } from 'rxjs';
import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger';

import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import {
  DialogService,
  AlertDialogComponent,
  AlertDialogResult,
  AlertDialogData
} from '@ucap-webmessenger/ui';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import {
  MessageApiService,
  MessageType,
  MessageList,
  MessageSearchType,
  MessageDetailInfo
} from '@ucap-webmessenger/api-message';
import { MessageStatusCode } from '@ucap-webmessenger/api';
import { ContentType } from '@ucap-webmessenger/api-message';
import { FormGroup, FormBuilder } from '@angular/forms';
import {
  MatTabGroup,
  MatSelectChange,
  MatRadioChange
} from '@angular/material';
import {
  MessageDetailDialogComponent,
  MessageDetailDialogResult,
  MessageDetailDialogData
} from '../../dialogs/message/message-detail.dialog.component';
import {
  EnvironmentsInfo,
  KEY_ENVIRONMENTS_INFO,
  KEY_VER_INFO
} from '@app/types';

import * as AppStore from '@app/store';
import * as MessageStore from '@app/store/messenger/message';
import { TranslateService } from '@ngx-translate/core';

export interface MessageTypeData {
  displayName: string;
  name: string;
}

@Component({
  selector: 'app-layout-chat-left-sidenav-message',
  templateUrl: './message.component.html',
  styleUrls: ['./message.component.scss']
})
export class MessageBoxComponent
  implements OnInit, OnDestroy, AfterViewChecked {
  @Input()
  isVisible = false;

  @Output()
  doRefreshUnReadCount = new EventEmitter();

  @ViewChild('tabs', { static: false }) tabs: MatTabGroup;
  isInitTabs = false;

  fgSearch: FormGroup;
  fgSearchType: FormGroup;

  loginRes: LoginResponse;
  sessionVerinfo: VersionInfo2Response;
  environmentsInfo: EnvironmentsInfo;

  messageRetrieveList$: Observable<MessageList[]>;
  messageSendList$: Observable<MessageList[]>;
  messageReservationList$: Observable<MessageList[]>;
  messageSearchList$: Observable<MessageList[]>;

  messageDetailInfo: Subscription;

  currentTabIndex = 0;
  defaultPageSize = 1000; // default

  currentTotalCount = 0;
  currentPage = 0;

  ContentType = ContentType;
  MessageType = MessageType;
  MessageSearchType = MessageSearchType;

  isSearch = false;

  messageTypeList: MessageTypeData[] = [];
  langChangeSubscription: Subscription;

  constructor(
    private store: Store<any>,
    private formBuilder: FormBuilder,
    private sessionStorageService: SessionStorageService,
    private dialogService: DialogService,
    private translateService: TranslateService,
    private messageApiService: MessageApiService,
    private logger: NGXLogger
  ) {
    this.loginRes = this.sessionStorageService.get<LoginResponse>(
      KEY_LOGIN_RES_INFO
    );
    this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
      KEY_VER_INFO
    );
    this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
      KEY_ENVIRONMENTS_INFO
    );
  }

  ngOnInit() {
    this.fgSearch = this.formBuilder.group({
      searchInput: null
    });
    this.fgSearchType = this.formBuilder.group({
      searchMessageType: [MessageType.All],
      searchMessageSearchType: [MessageSearchType.Name]
    });

    this.messageRetrieveList$ = this.store.pipe(
      select(AppStore.MessengerSelector.MessageSelector.selectAllReceiveList)
    );

    this.messageSendList$ = this.store.pipe(
      select(AppStore.MessengerSelector.MessageSelector.selectAllSendList)
    );
    this.messageReservationList$ = this.store.pipe(
      select(
        AppStore.MessengerSelector.MessageSelector.selectAllReservationList
      )
    );
    this.messageSearchList$ = this.store.pipe(
      select(AppStore.MessengerSelector.MessageSelector.selectAllSearchList)
    );

    this.messageDetailInfo = this.store
      .pipe(
        select(AppStore.MessengerSelector.MessageSelector.detailMessageInfo)
      )
      .subscribe(async info => {
        if (!!info && info.responseCode === MessageStatusCode.Success) {
          // Badge Refresh in case Receive Message..
          if (info.msgInfo.type === MessageType.Receive) {
            this.doRefreshUnReadCount.emit();

            // Clear Receive Message New Badge..
            this.store.dispatch(
              MessageStore.clearNewFlagReceiveMessage({
                msgId: info.msgInfo.msgId
              })
            );
          }

          // detail view..
          const result = await this.dialogService.open<
            MessageDetailDialogComponent,
            MessageDetailDialogData,
            MessageDetailDialogResult
          >(MessageDetailDialogComponent, {
            width: '600px',
            data: {
              detail: info,
              loginRes: this.loginRes,
              environmentsInfo: this.environmentsInfo
            }
          });

          if (!!result) {
            // Clear detail Info in state
            this.store.dispatch(MessageStore.detailMessageClear({}));

            switch (result.returnType) {
              case 'DEL':
                // 단건 삭제.
                this.doMessageDelete([result.messageInfo]);
                break;
              case 'CANCEL_RESERVATION':
                // 단건 발송취소(예약)
                this.doMessageCancelReservation(result.messageInfo);
                break;
              case 'UPDATE':
                // 예약 수정
                this.getRetrieveMessage(MessageType.Reservation, 0);
                break;
            }
          }
        } else if (
          !!info &&
          info.responseCode === MessageStatusCode.Fail_Cancelled_Msg
        ) {
          this.dialogService.open<
            AlertDialogComponent,
            AlertDialogData,
            AlertDialogResult
          >(AlertDialogComponent, {
            width: '360px',
            data: {
              title: this.translateService.instant('message.errors.label'),
              message: this.translateService.instant(
                'message.errors.cancelledMessage'
              )
            }
          });
        }
      });

    // 초기 검색은 수신함.
    this.getRetrieveMessage(MessageType.Receive, 0);

    if (!!this.tabs) {
      this.tabs.realignInkBar();
    }

    this.setMessageTypeData();
    this.langChangeSubscription = merge(
      this.translateService.onLangChange,
      this.translateService.onDefaultLangChange,
      this.translateService.onTranslationChange
    ).subscribe(() => {
      this.setMessageTypeData();
    });
  }

  ngAfterViewChecked(): void {
    if (!!this.tabs && !this.isInitTabs && this.isVisible) {
      this.isInitTabs = true;
      this.tabs.realignInkBar();
    }
  }

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

  onSelectedIndexTab(value: number) {
    this.tabs.selectedIndex = value;
  }
  onSelectedIndexChange(value: number) {
    this.currentTabIndex = value;
    let messageType: MessageType;
    switch (value) {
      case 0:
        // Recieve
        messageType = MessageType.Receive;
        break;
      case 1:
        // Send
        messageType = MessageType.Send;
        break;
      case 2:
        // Reservation
        messageType = MessageType.Reservation;
        break;
    }

    this.getRetrieveMessage(messageType, 0);
  }

  /** 쪽지 검색 관련 */
  onChangeSelection(event: MatSelectChange) {
    this.getSearchMessage(
      event.value,
      this.fgSearchType.get('searchMessageSearchType').value,
      this.fgSearch.get('searchInput').value
    );
  }
  onChangeSearchType(event: MatRadioChange) {
    this.getSearchMessage(
      this.fgSearchType.get('searchMessageType').value,
      event.value,
      this.fgSearch.get('searchInput').value
    );
  }
  onKeyDownEnter(event: KeyboardEvent, search: string) {
    event.preventDefault();
    event.stopPropagation();

    if (!search || search.trim().length === 0) {
      return;
    }

    this.getSearchMessage(
      MessageType.All,
      MessageSearchType.Name,
      search.trim()
    );
  }
  getSearchMessage(
    messageType: MessageType,
    searchType: MessageSearchType,
    searchStr: string
  ) {
    this.isSearch = true;

    this.store.dispatch(
      MessageStore.searchMessage({
        messageType,
        searchType,
        searchStr
      })
    );
  }
  onClickSearchCancel() {
    this.isSearch = false;
    this.store.dispatch(MessageStore.clearSearchMessage({}));
    // this.getRetrieveMessage(MessageType.Receive, 0);
  }

  /** 쪽지 타입별 조회 */
  getRetrieveMessage(messageType: MessageType, trgtPageIndex: number) {
    this.store.dispatch(
      MessageStore.retrieveMessage({
        messageType
      })
    );
  }

  /** 쪽지 상세보기 */
  onClickDetail(message: MessageList) {
    this.store.dispatch(
      MessageStore.detailMessage({
        messageType: message.type,
        msgId: message.msgId
      })
    );
  }

  /** 쪽지(수신,발신) 삭제 */
  doMessageDelete(messageInfo: MessageDetailInfo[]): void {
    const msgList: { msgId: number }[] = [];
    messageInfo.forEach(info => msgList.push({ msgId: info.msgId }));

    this.store.dispatch(
      MessageStore.deleteMessage({
        messageType: messageInfo[0].type,
        msgList
      })
    );
  }

  /** 쪽지(예약) 삭제 */
  doMessageCancelReservation(messageInfo: MessageDetailInfo): void {
    this.store.dispatch(
      MessageStore.cancelReservationMessage({
        messageType: messageInfo.type,
        msgId: messageInfo.msgId
      })
    );
  }

  private setMessageTypeData() {
    const messageTypeData = this.translateService.instant('message.type');

    const messageTypeList: MessageTypeData[] = [];
    for (const key in messageTypeData) {
      if (messageTypeData.hasOwnProperty(key)) {
        let name = 'A';
        switch (key) {
          case 'messageTypeAll':
            name = MessageType.All;
            break;
          case 'messageTypeReceiving':
            name = MessageType.Receive;
            break;
          case 'messageTypeOutgoing':
            name = MessageType.Send;
            break;
          case 'messageTypeReservation':
            name = MessageType.Reservation;
            break;
        }
        messageTypeList.push({ displayName: messageTypeData[key], name });
      }
    }

    this.messageTypeList = messageTypeList;
  }
}
