import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { AccountService } from 'src/app/shared/server-services/account.service';
import {
  RoomData,
  RoomRecord,
  RoomWithData,
} from 'src/app/shared/server-services/query-records/room-records';
import { SidebarResource } from 'src/app/shared/server-services/query-records/sidebar-records';
import { WorkspaceSubscriptionRoomEventRecord } 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 { RouterHandler } from 'src/app/shared/services/router-handler.service';
import { sideMenuActiveObserver } from 'src/app/shared/shared-observers';

@Component({
  selector: 'app-sidebar-room',
  templateUrl: './sidebar-room.component.html',
  styleUrls: ['./sidebar-room.component.scss'],
})
export class SidebarRoomComponent implements OnInit, OnDestroy {
  @Input() sidebarResourceData: SidebarResource | RoomRecord;

  public room: RoomRecord;
  public roomData: RoomData;

  public avatar: ArrayBuffer;
  public name: string;
  public error: boolean;
  public news: boolean;

  public selectedMenu = false;

  public isNanoConnected: boolean = false;
  public isNanoCompeting: boolean = false;
  public isMyRoom: boolean = false;

  private onRouterChange = (res) => {
    this.selectedMenu = this.sidebarResourceData.id == res?.params?.id;
  };

  constructor(
    private routerHandler: RouterHandler,
    private subscriptionService: SubscriptionService,
    private roomService: RoomService,
    private accountService: AccountService
  ) {
    this.routerHandler.subscribeAll(this.onRouterChange);

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

    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.ROOM_ACCOUNT_PERMISSION_EVENT,
      SubscriptionServiceEventType.CREATE,
      this.updateData
    );

    this.subscriptionService.subscribe(
      SubscriptionServiceEvent.ROOM_ACCOUNT_PERMISSION_EVENT,
      SubscriptionServiceEventType.DELETE,
      this.updateData
    );
  }

  ngOnInit(): void {
    // RoomData is not necessary here
    // only after the component is visible
    this.loadRoomRecord().then(() => {
      this.refreshState();
      this.accountService.getMe().then((me) => {
        this.isMyRoom = this.room.ownerAccountId == me.id;
      });
    });
  }

  private updateData = (event: WorkspaceSubscriptionRoomEventRecord) => {
    if (this.sidebarResourceData.id == event.id) {
      if (event.data) {
        // data in the cache, refresh the data with that
        this.loadRoomData();
      } else {
        // not sure if data in the cache, return with the optimized query
        this.loadRoomRecord();
      }
      this.refreshState();
    }
  };

  public visibilityChange(visible: boolean) {
    if (!this.roomData && visible) {
      this.loadRoomData();
    }
  }

  // load the data object on the component
  private loadRoomData(): Promise<void> {
    return this.roomService
      .getRoom(this.sidebarResourceData.id)
      .then((room) => {
        this.room = room;
        this.roomData = room.data;
        this.refreshState();
        return;
      })
      .catch((err) => {
        console.warn('can not find room', err);
        return;
      });
  }

  // load the record, we dont need the data, so we dont start a query for that
  // but there is a chance it is already in the cache
  private loadRoomRecord(): Promise<void> {
    return this.roomService.getRoomRecord(this.sidebarResourceData.id).then((room) => {
      this.room = room;
      // the data is already in the cache, or it is generated a full server request
      if ((<RoomWithData>room).data) {
        this.roomData = (<RoomWithData>room).data;
      }
      this.refreshState();
      return;
    });
  }

  /**
   * Refresh all the view-based variables to trigger changes
   */
  private refreshState() {
    if (this.room.nanoSessions) {
      this.isNanoConnected = Object.keys(this.room.nanoSessions).length > 0;
      this.isNanoCompeting = Object.keys(this.room.nanoSessions).length > 1;
    }
    if (this.roomData) {
      if (this.roomData.decryptionError) {
        this.error = true;
        this.name = this.roomData.decryptionErrorMessage;
      } else {
        this.error = false;
        this.name = this.roomData.name;
        this.avatar = this.roomData.avatar;
      }
    }
    this.news =
      (this.room.seenMessageId == null && this.room.topMessageId !== null) ||
      this.room.seenMessageId < this.room.topMessageId;
  }

  ngOnDestroy(): void {
    this.routerHandler.unsubscribeAll(this.onRouterChange);
    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_EVENT,
      SubscriptionServiceEventType.MODIFY,
      this.updateData
    );

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_ACCOUNT_PERMISSION_EVENT,
      SubscriptionServiceEventType.CREATE,
      this.updateData
    );

    this.subscriptionService.unsubscribe(
      SubscriptionServiceEvent.ROOM_ACCOUNT_PERMISSION_EVENT,
      SubscriptionServiceEventType.DELETE,
      this.updateData
    );
  }

  hideSidebar(): void {
    this.loadRoomData();
    sideMenuActiveObserver.next(false);
  }
}
