import {
  Subject,
  Observable,
  BehaviorSubject,
  Subscription,
  merge
} from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import {
  Component,
  OnInit,
  OnDestroy,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Input
} from '@angular/core';
import { Info, EventJson, EventType, FileType } from '@ucap/protocol-event';
import { Store, select } from '@ngrx/store';
import { Chatting } from '@ucap/ng-store-chat/lib/store/chatting/state';
import { ChattingSelector, RoomSelector } from '@ucap/ng-store-chat';
import {
  UserInfo as RoomUserInfo,
  UserInfoShort as RoomUserInfoShort,
  RoomInfo
} from '@ucap/protocol-room';
import { LoginResponse } from '@ucap/protocol-authentication';
import {
  LoginSelector,
  ConfigurationSelector
} from '@ucap/ng-store-authentication';
import { AppChatService } from '@app/services/app-chat.service';
import { VersionInfo2Response } from '@ucap/api-public';
import moment from 'moment';
import { Dictionary } from '@ngrx/entity';

@Component({
  selector: 'app-sections-chat-message',
  templateUrl: './message.section.component.html',
  styleUrls: ['./message.section.component.scss'],

  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MessageSectionComponent implements OnInit, OnDestroy {
  @Input()
  set roomId(roomId: string) {
    this._roomId = roomId;

    this.roomIdSubject.next(roomId);

    this.initializeRoomData();
  }
  get roomId(): string {
    return this._roomId;
  }
  // tslint:disable-next-line: variable-name
  _roomId: string;

  versionInfo2Res: VersionInfo2Response;
  loginRes: LoginResponse;

  roomIdSubject = new Subject<string>();

  currentRoomInfo: RoomInfo;
  chatting$: Observable<Chatting>;
  roomUsers: RoomUserInfoShort[] = [];
  // eventList$: Observable<Info<EventJson>[]>;
  eventList: Info<EventJson>[];

  defaultProfileImage: string;
  EventType = EventType;
  FileType = FileType;

  private ngOnDestroySubject = new Subject<boolean>();
  constructor(
    private appChatService: AppChatService,
    private store: Store<any>,
    private changeDetectorRef: ChangeDetectorRef
  ) {
    this.defaultProfileImage = this.appChatService.defaultProfileImage;
  }

  ngOnInit(): void {
    this.store
      .pipe(
        takeUntil(this.ngOnDestroySubject),
        select(ConfigurationSelector.versionInfo2Response)
      )
      .subscribe((versionInfo2Res) => {
        this.versionInfo2Res = versionInfo2Res;
      });
    this.store
      .pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
      .subscribe((loginRes) => {
        this.loginRes = loginRes;
      });

    this.store
      .pipe(
        takeUntil(this.ngOnDestroySubject),
        select(
          (state: any) => state.chat.room.rooms.entities as Dictionary<RoomInfo>
        )
      )
      .subscribe((rooms) => {
        if (!!this.roomId) {
          this.currentRoomInfo = rooms[this.roomId];
        }
      });
  }

  initializeRoomData() {
    this.chatting$ = this.store.pipe(
      takeUntil(merge(this.ngOnDestroySubject, this.roomIdSubject)),
      select(ChattingSelector.chatting, this.roomId)
    );

    this.store
      .pipe(
        takeUntil(merge(this.ngOnDestroySubject, this.roomIdSubject)),
        select(ChattingSelector.eventList, this.roomId)
      )
      .subscribe((eventList) => {
        this.eventList = eventList;

        this.changeDetectorRef.detectChanges();
      });

    this.store
      .pipe(
        takeUntil(merge(this.ngOnDestroySubject, this.roomIdSubject)),
        select(RoomSelector.roomUserShort, this.roomId)
      )
      .subscribe((roomUserShort) => {
        if (!!roomUserShort) {
          this.roomUsers = roomUserShort.userInfos;
        }
      });
  }

  ngOnDestroy(): void {
    if (!!this.ngOnDestroySubject) {
      this.ngOnDestroySubject.complete();
    }
  }

  /** Sender Info */
  getSenderInfo(
    senderSeq: number
  ): RoomUserInfoShort | RoomUserInfo | undefined {
    if (!!this.roomUsers && this.roomUsers.length) {
      return this.roomUsers.find(
        (userInfo) => userInfo.seq + '' === senderSeq + ''
      );
    }

    return undefined;
  }

  /** Date Splitter show check */
  getDateSplitter(event: Info<EventJson>): boolean {
    const curIndex = this.eventList.findIndex((v) => v.seq === event.seq);

    if (curIndex === 0) {
      return true;
    }
    if (curIndex > 0) {
      if (!this.eventList[curIndex]) {
        return false;
      }
      return !moment(this.eventList[curIndex].sendDate).isSame(
        moment(this.eventList[curIndex - 1].sendDate),
        'day'
      );
    }
    return false;
  }

  /** Unread Count calculation */
  getUnreadCount(message: Info<EventJson>): string | number {
    const unreadCnt = this.roomUsers
      .filter(
        (user) => user.isJoinRoom && user.seq + '' !== message.senderSeq + ''
      )
      .filter((user) => user.lastReadEventSeq < message.seq).length;
    return unreadCnt === 0 ? '' : unreadCnt;
  }
}
