import { Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { AppStorage } from 'src/app/shared/app-storage';
import { AccountService } from 'src/app/shared/server-services/account.service';
import { MeRecord } from 'src/app/shared/server-services/query-records/account-records';
import { RoomRecord } from 'src/app/shared/server-services/query-records/room-records';
import {
  WorkspaceSubscriptionDialogueEventRecord,
  WorkspaceSubscriptionRoomEventRecord
} from 'src/app/shared/server-services/query-records/workspace-records';
import { RoomService } from 'src/app/shared/server-services/room.service';
import {
  SearchMode,
  SearchResult,
  SearchService
} from 'src/app/shared/server-services/search-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';

@Component({
  selector: 'app-search-view',
  templateUrl: './search-view.component.html',
  styleUrls: ['./search-view.component.scss'],
})
export class SearchViewComponent implements OnInit, OnDestroy {
  public query;
  public searchResults: SearchResult[] = [];
  public resourceId;
  public showFilterSearchPanel: boolean = false;
  public allRooms: RoomRecord[] = [];
  private ownRooms: RoomRecord[] = [];
  public selectedRoomIds: string[] = [];
  private selectedRooms: RoomRecord[] = [];
  private me: MeRecord;
  public searchMode: SearchMode = SearchMode.GLOBAL;
  public SearchMode = SearchMode;

  public dragging: boolean = false;
  public searchBoxHeight: number;

  @ViewChild('searchBox', { static: false }) searchBox: ElementRef;

  public searchHandler = (resourceId, query, results) => {
    this.searchResults = this.searchService.getResults();
    this.loadInitData();
  };

  public onRouteChange = (res) => {
    if (!this.searchService.isSearchInProgress()) {
      this.showFilterSearchPanel = true;
    } else {
      this.searchResults = this.searchService.getResults();
      this.showFilterSearchPanel = false;
    }
  };

  private roomEditedTimeout;
  private onEditRoom = (
    data: WorkspaceSubscriptionRoomEventRecord | WorkspaceSubscriptionDialogueEventRecord
  ) => {
    // console.log("workspace subscription room event", data);
    // if (this.roomEditedTimeout) clearTimeout(this.roomEditedTimeout);
    // this.roomEditedTimeout = setTimeout(() => {
    //   this.loadInitData();
    //   this.redoSearch();
    // }, 2000);
  };

  constructor(
    private searchService: SearchService,
    private routerHandler: RouterHandler,
    private roomService: RoomService,
    private accountService: AccountService,
    private subscriptionService: SubscriptionService
  ) {}

  ngOnInit(): void {
    this.loadInitData();

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

    this.routerHandler.subscribe('search', this.onRouteChange);
    if (this.routerHandler.isOnPage('search')) {
      this.onRouteChange(this.routerHandler.getRoute());
    }

    this.searchService.subscribe(this.searchHandler);
    this.searchResults = this.searchService.getResults();
  }

  loadInitData(): void {
    this.accountService.getMe().then((me) => (this.me = me));
    this.roomService.getAllRoomWithActiveDrive().then((rooms) => {
      let p = [];
      rooms.forEach((r) => {
        p.push(this.roomService.getRoom(r.id));
      });
      Promise.all(p).then(() => {
        this.allRooms = rooms;
        let roomIds = this.searchService.getSelectedResourceIds();
        if (roomIds.length == 0 || roomIds.length == this.allRooms.length) {
          this.selectedRoomIds = this.allRooms.map((room) => room.id);
        } else {
          this.selectedRoomIds = this.allRooms
            .filter((room) => roomIds.some((roomId) => roomId == room.id))
            .map((room) => room.id);
        }

        this.ownRooms = this.allRooms.filter((room) => room.ownerAccountId === this.me.id);

        this.updateSearchMode();
      });
    });
  }

  redoSearch(): void {
    let resourceIds = this.selectedRoomIds;
    let fragment = this.routerHandler.getRoute().fragment;
    this.searchService.search(fragment.search, resourceIds);
    this.showFilterSearchPanel = false;

    if (!this.routerHandler.isOnPage('search')) {
      console.log('not on search page');

      this.routerHandler.navigate(['/search/', resourceIds.join(',')], {
        fragment: this.routerHandler.fragmentToRaw(fragment),
      });
    }

    this.updateSearchMode();
  }

  ngOnDestroy() {
    this.searchService.unsubscribe(this.searchHandler);
    this.routerHandler.unsubscribe('search', this.onRouteChange);

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

  roomChecked(checkedRoom: RoomRecord): void {
    if (this.searchService.isSearchInProgress()) return;

    if (!this.selectedRoomIds.some((roomIds) => roomIds == checkedRoom.id)) {
      this.selectedRoomIds.push(checkedRoom.id);
    } else {
      this.selectedRoomIds = this.selectedRoomIds.filter((roomId) => roomId != checkedRoom.id);
    }

    //this.updateSearchMode();
  }

  isRoomSelected(room: RoomRecord): boolean {
    return this.selectedRoomIds.some((selectedRoomId) => selectedRoomId == room.id);
  }

  isMyRoom(room: RoomRecord): boolean {
    return room.ownerAccountId == this.me.id;
  }

  selectOwnRooms() {
    this.selectedRoomIds = this.ownRooms.map((room) => room.id);
  }

  clearSelection() {
    this.selectedRoomIds = [];
  }

  selectAll() {
    this.selectedRoomIds = this.allRooms.map((room) => room.id);
  }

  updateSearchMode(): void {
    let allRoomIds = this.allRooms.map((room) => room.id);
    let ownRoomIds = this.ownRooms.map((room) => room.id);
    if (
      this.selectedRoomIds.length == allRoomIds.length &&
      this.selectedRoomIds.every((sri) => allRoomIds.indexOf(sri) > -1)
    ) {
      this.searchMode = SearchMode.GLOBAL;
    } else if (
      this.selectedRoomIds.length == ownRoomIds.length &&
      this.selectedRoomIds.every((sri) => ownRoomIds.indexOf(sri) > -1)
    ) {
      this.searchMode = SearchMode.ROOM;
    } else {
      this.searchMode = SearchMode.CUSTOM;
      this.selectedRooms = this.allRooms.filter(
        (room) => this.selectedRoomIds.indexOf(room.id) > -1
      );
    }
  }

  get isSearching(): boolean {
    return this.searchService.isSearchInProgress();
  }

  private startY;
  private startHeight;
  public draggerPointerDown(e: MouseEvent) {
    this.dragging = true;
    this.startY = e.clientY;
    this.startHeight = parseInt(
      document.defaultView.getComputedStyle(this.searchBox.nativeElement).height,
      10
    );
  }
  @HostListener('document:pointerup', ['$event']) pointerUp(e: MouseEvent) {
    if (this.dragging) {
      this.dragging = false;
      AppStorage.setItem('searchBoxHeight', e.clientX.toString());
    }
  }
  @HostListener('document:mousemove', ['$event'])
  onMouseMove(e: MouseEvent) {
    if (this.dragging) {
      this.searchBoxHeight = this.startHeight + e.clientY - this.startY;
    }
  }
}
