import { Component, OnDestroy, OnInit } from '@angular/core';
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import { TranslateService } from '@ngx-translate/core';
import { base64 } from 'rfc4648';
import { AccountService } from 'src/app/shared/server-services/account.service';
import { AuthService } from 'src/app/shared/server-services/auth.service';
import { DialogueService } from 'src/app/shared/server-services/dialogue.service';
import { AccountAvatarRecord } from 'src/app/shared/server-services/query-records/account-records';
import { DialogueRecord } from 'src/app/shared/server-services/query-records/room-records';
import {
  WorkspaceSubscriptionDialogueEventRecord,
  WorkspaceSubscriptionRoomAccountPermissionEventRecord,
  WorkspaceSubscriptionRoomEventRecord,
  WorkspaceSubscriptionRoomPermissionEventRecord,
} from 'src/app/shared/server-services/query-records/workspace-records';
import { RoomService } from 'src/app/shared/server-services/room.service';
import {
  SubscriptionServiceEvent,
  SubscriptionServiceEventType,
} from 'src/app/shared/server-services/subscription-event';
import { SubscriptionService } from 'src/app/shared/server-services/subscription.service';
import { DialogService } from 'src/app/shared/services/dialog.service';
import { RouterHandler } from 'src/app/shared/services/router-handler.service';
import { SnackBarService } from 'src/app/shared/services/snackbar.service';
import { TitleService } from 'src/app/shared/services/title.service';

@Component({
  selector: 'app-resource-page',
  templateUrl: './resource-page.component.html',
  styleUrls: ['./resource-page.component.scss'],
})
export class ResourcePageComponent implements OnInit, OnDestroy {
  public activeMenu = 'chat';
  public resourceId;
  public resourceName = '';
  public roomImage: ArrayBuffer;
  public avatar: AccountAvatarRecord;
  public routeSubscription;
  public dataLoaded = false;
  public loadError = true;
  public pinnedKey = '';
  public isReadOnly: boolean = false;
  public isMessageboard: boolean = false;
  public showNewMessageCircle: boolean = false;
  public isBlocked;

  public onRouterChangeChat = (res) => {
    this.onChangeRoute(
      res,
      res.params.type !== 'room' ? 'private' : 'chat',
      res.params.type !== 'private'
    );
  };

  public onRouterChangeDrive = (res) => {
    this.onChangeRoute(res, 'drive', res.params.type !== 'chat');
  };

  public onRouterChangeDetails = (res) => {
    this.onChangeRoute(res, 'details', res.params.type !== 'chat');
  };

  private checkReadOnly() {
    if (this.authService.isAnonym()) {
      this.isReadOnly = true;
    } else {
      this.roomService
        .getMyRoomPermissions(this.resourceId)
        .then((res) => {
          this.isReadOnly = false;
        })
        .catch(() => {
          this.isReadOnly = true;
        });
    }
  }

  private onChangeRoute(res, activeMenu, isRoom = true) {
    this.activeMenu = activeMenu;

    let outerPinnedKey;

    if (res.fragment?.roomkey) {
      // TODO paralell fragmentation
      outerPinnedKey = res.fragment.roomkey;
    }

    if (
      !this.resourceId ||
      this.resourceId != res.params.id ||
      (isRoom && this.pinnedKey != outerPinnedKey)
    ) {
      this.resourceId = res.params.id;
      this.roomImage = null;
      this.dataLoaded = false;
      this.loadError = false;

      if (isRoom) {
        this.checkReadOnly();

        this.pinnedKey = outerPinnedKey;
        let parsedPinnedKey: Uint8Array;

        if (this.pinnedKey) {
          try {
            parsedPinnedKey = base64.parse(this.pinnedKey);
          } catch (e) {
            console.error('can not parse pinned key');
            // just try to load the room without pinned key
            // if it fails, we response with error message
            // there is a chance, we do not need the pinned key
            // when we are logged in and we are member of the room
          }
        }
        if (this.pinnedKey) {
          this.roomService.registerPinnedKey(this.resourceId, this.pinnedKey);
        }

        this.roomService
          .getRoom(this.resourceId)
          .then((res) => {
            if (res) {
              this.roomService
                .getMyRoomPermissions(this.resourceId)
                .then((perm) => {
                  this.isMessageboard = perm.msgBrdReadOnly;
                })
                .catch((err) => {
                  console.log('could not load room perm', this.resourceId);
                });
              this.resourceName = res.data?.name;
              this.roomImage = res.data?.avatar;
              this.avatar = null;
              this.dataLoaded = true;
              this.showNewMessageCircle =
                (res.seenMessageId == null && res.topMessageId !== null) ||
                res.seenMessageId < res.topMessageId;
              console.log('data loaded', this.resourceName);
              this.titleService.setTabTitle(this.resourceName);
            } else {
              console.error('there is no response from get data');
              this.loadError = false;
            }
          })
          .catch((err) => {
            console.error('could not load room data', err);
            this.loadError = true;
          });
      } else {
        this.dialogueService
          .getData(this.resourceId)
          .then((dialogueRecord: DialogueRecord) => {
            this.isBlocked = dialogueRecord.hidden;

            this.accountService.getAccount(dialogueRecord.id).then((acc) => {
              this.resourceName = acc.deleted
                ? this.translateService.instant(marker('Deleted user'))
                : acc.avatarName;
              this.dataLoaded = true;
              this.avatar = acc;
              this.roomImage = null;

              this.showNewMessageCircle =
                (dialogueRecord.seenMessageId == null && dialogueRecord.topMessageId !== null) ||
                dialogueRecord.seenMessageId < dialogueRecord.topMessageId;
              this.titleService.setTabTitle(this.resourceName);
            });
          })
          .catch((err) => {
            console.error('could not load dialogue data', err);
            this.loadError = true;
          });
      }
    }

    this.resourceId = res.params.id;
  }

  public onRoomDataChanged = (res: WorkspaceSubscriptionRoomEventRecord) => {
    if (res.id == this.resourceId) {
      if ('data' in res && 'name' in res.data) {
        this.resourceName = res.data.name;
      }

      if ('data' in res && 'avatar' in res.data) {
        this.roomImage = res.data.avatar;
      }

      if (res?.seenMessageId || res?.topMessageId) {
        this.roomService.getRoom(res.id).then((room) => {
          if (room) {
            this.showNewMessageCircle =
              (room.seenMessageId == null && room.topMessageId !== null) ||
              room.seenMessageId < room.topMessageId;
          }
        });
      }
    }
  };

  public onDialogueDataChanged = (res: WorkspaceSubscriptionDialogueEventRecord) => {
    if (res.id == this.resourceId) {
      if (res?.seenMessageId || res?.topMessageId) {
        this.dialogueService.getData(res.id).then((dialogue) => {
          this.showNewMessageCircle =
            (dialogue.seenMessageId == null && dialogue.topMessageId !== null) ||
            dialogue.seenMessageId < dialogue.topMessageId;
        });
      }
    }
  };

  constructor(
    private routerHandler: RouterHandler,
    private roomService: RoomService,
    private accountService: AccountService,
    private titleService: TitleService,
    private subscriptionService: SubscriptionService,
    private dialogueService: DialogueService,
    private authService: AuthService,
    private dialogService: DialogService,
    private translateService: TranslateService,
    private snackbarService: SnackBarService
  ) {
    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.DIALOGUE_EVENT,
      SubscriptionServiceEventType.MODIFY,
      this.onDialogueDataChanged
    );

    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.ROOM_EVENT,
      SubscriptionServiceEventType.MODIFY,
      this.onRoomDataChanged
    );

    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.ROOM_ACCOUNT_PERMISSION_EVENT,
      SubscriptionServiceEventType.ALL,
      this.onRoomAccountPermissionChange
    );

    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.ROOM_PERMISSION_EVENT,
      SubscriptionServiceEventType.ALL,
      this.onRoomPermissionChange
    );

    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.ROOM_MESSAGE_EVENT,
      SubscriptionServiceEventType.CREATE,
      this.onMessageEvent
    );
  }

  private onRoomAccountPermissionChange = (
    event: WorkspaceSubscriptionRoomAccountPermissionEventRecord
  ) => {
    if (event.id == this.resourceId) {
      this.checkReadOnly();
      this.snackbarService.showSnackbar(marker('Your permission has changed for this room.'));
    }
  };

  private onRoomPermissionChange = (event: WorkspaceSubscriptionRoomPermissionEventRecord) => {
    if (event.id == this.resourceId) {
      this.isMessageboard = event.msgBrdReadOnly;
    }
  };

  private onMessageEvent = (event) => {
    if (this.activeMenu != 'chat') this.showNewMessageCircle = true;
  };

  public changeMenu(menu) {
    this.activeMenu = menu;
    if (this.activeMenu == 'chat') this.showNewMessageCircle = false;
  }

  ngOnInit(): void {
    if (this.routerHandler.isOnPage('room/?/chat/?')) {
      this.onRouterChangeChat(this.routerHandler.getRoute());
    }
    this.routerHandler.subscribe('room/?/chat/?', this.onRouterChangeChat);

    if (this.routerHandler.isOnPage('room/?/drive')) {
      this.onRouterChangeDrive(this.routerHandler.getRoute());
    }
    this.routerHandler.subscribe('room/?/drive', this.onRouterChangeDrive);

    if (this.routerHandler.isOnPage('room/?/details')) {
      this.onRouterChangeDetails(this.routerHandler.getRoute());
    }
    this.routerHandler.subscribe('room/?/details', this.onRouterChangeDetails);
  }

  ngOnDestroy() {
    this.routerHandler.unsubscribe('room/?/chat/?', this.onRouterChangeChat);
    this.routerHandler.unsubscribe('room/?/drive', this.onRouterChangeDrive);
    this.routerHandler.unsubscribe('room/?/details', this.onRouterChangeDetails);

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.DIALOGUE_EVENT,
      SubscriptionServiceEventType.MODIFY,
      this.onDialogueDataChanged
    );

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_EVENT,
      SubscriptionServiceEventType.MODIFY,
      this.onRoomDataChanged
    );

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_ACCOUNT_PERMISSION_EVENT,
      SubscriptionServiceEventType.ALL,
      this.onRoomAccountPermissionChange
    );

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_PERMISSION_EVENT,
      SubscriptionServiceEventType.ALL,
      this.onRoomPermissionChange
    );

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_MESSAGE_EVENT,
      SubscriptionServiceEventType.CREATE,
      this.onMessageEvent
    );
  }

  openChat() {
    this.routerHandler
      .navigate(['/room/' + this.resourceId + '/chat/room'], {
        fragment: this.routerHandler.getRoute().rawFragment,
      })
      .then((navigated: boolean) => {
        if (navigated) this.changeMenu('chat');
      });
  }

  openDrive() {
    this.routerHandler
      .navigate(['/room/' + this.resourceId + '/drive'], {
        fragment: this.routerHandler.getRoute().rawFragment,
      })
      .then((navigated: boolean) => {
        if (navigated) this.changeMenu('drive');
      });
  }

  openDetails() {
    this.routerHandler
      .navigate(['/room/' + this.resourceId + '/details'], {
        fragment: this.routerHandler.getRoute().rawFragment,
      })
      .then((navigated: boolean) => {
        if (navigated) this.changeMenu('details');
      });
  }

  blockUser() {
    this.dialogService
      .openConfirmDialog(marker('Block user'), marker('Are you sure you want to block this user?'))
      .subscribe((confirmed) => {
        if (!confirmed) return;

        this.accountService.blockUser(this.resourceId).then(() => {
          this.snackbarService.showSnackbar(marker('User blocked.'));
          this.isBlocked = true;
        });
      });
  }

  unblockUser() {
    this.accountService.unblockUser(this.resourceId).then(() => {
      this.snackbarService.showSnackbar(marker('User unblocked.'));
      this.isBlocked = false;
    });
  }

  get isAnon(): boolean {
    return this.authService.isAnonym();
  }
}
