import {
  AfterViewInit,
  Component,
  ElementRef,
  HostBinding,
  HostListener,
  OnInit,
  ViewChild,
} from "@angular/core";
import { MatMenuTrigger } from "@angular/material/menu";
import { Subject } from "rxjs";
import { EnvironmentService } from "src/environments/environment.service";
import { AccountAvatarRecord } from "../../server-services/query-records/account-records";
import { DialogService } from "../../services/dialog.service";
import { marker } from "@biesbjerg/ngx-translate-extract-marker";
import { ServerRestApiService } from "../../services/server-rest-api.service";
import {
  createContactQuery,
  getContactListQuery,
} from "../../server-services/querys";
import { AccountService } from "../../server-services/account.service";
import { SubscriptionService } from "../../server-services/subscription.service";
import { RouterHandler } from "../../services/router-handler.service";
import { Router } from "@angular/router";
import { DialogueService } from "../../server-services/dialogue.service";
import { AuthService } from "../../server-services/auth.service";
import { environment } from "src/environments/environment";
import { ClipboardService } from "../../services/clipboard.service";

export let showUserInfoObserver = new Subject<{
  avatarInfo: AccountAvatarRecord;
  originElementRef: ElementRef;
}>();

@Component({
  selector: "app-user-info-menu",
  templateUrl: "./user-info-menu.component.html",
  styleUrls: ["./user-info-menu.component.scss"],
})
export class UserInfoMenuComponent implements AfterViewInit, OnInit {
  public avatar: AccountAvatarRecord;
  public me: AccountAvatarRecord;
  private contactList: AccountAvatarRecord[];
  public avatarInContacts: boolean = false;
  public avatarRoomUrl: string;
  public inCurrentRoom: boolean = false;
  public isAnonymous: boolean = false;

  private originElementRef: ElementRef;
  @HostBinding("style.top") public top: string = "0px";
  @HostBinding("style.left") public left: string = "0px";
  @ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger;

  private marginRight: number = 10;
  private menuAnimationInMillis: number = 0.25 * 1000;
  private menuFullyOpen: boolean = false;

  constructor(
    private thisElementRef: ElementRef,
    private environmentService: EnvironmentService,
    private dialogService: DialogService,
    private dialogueService: DialogueService,
    private serverRestApiService: ServerRestApiService,
    private accountService: AccountService,
    private authService: AuthService,
    private subscriptionService: SubscriptionService,
    private router: Router,
    private routerHandler: RouterHandler,
    private clipboardService: ClipboardService
  ) {}
  async ngOnInit(): Promise<void> {
    this.subscriptionService.subscribeWorkspaceLoaded(async () => {
      [this.me, this.contactList] = await Promise.all([
        this.accountService.getMe(),
        this.serverRestApiService.query({ query: getContactListQuery }),
      ]);

      this.isAnonymous = this.authService.isAnonym();
    });
  }

  ngAfterViewInit(): void {
    showUserInfoObserver.subscribe((clickData) => {
      if (
        this.menuFullyOpen &&
        this.originElementRef == clickData.originElementRef
      )
        return;

      this.originElementRef = clickData.originElementRef;

      if (this.menuTrigger.menuOpen) {
        this.closeThenOpenMenu(clickData.avatarInfo);
      } else this.openMenu(clickData.avatarInfo);
    });
  }

  public copyContactId() {
    this.clipboardService
      .copy(this.avatar.id)
      .then(() => {
        this.dialogService.showSnackbar(marker("Contact ID copied!"));
      })
      .catch((err) => {
        console.error("clipboard err", err);
        this.dialogService.openAlertDialog(
          marker("Copy Error"),
          marker("Could not copy to the clipboard")
        );
      });
  }

  copyContactUrl() {
    this.clipboardService
      .copy(
        environment.site_base +
          "#contact" +
          RouterHandler.FRAGMENT_EQUAL +
          this.avatar.id
      )
      .then(() => {
        this.dialogService.showSnackbar(marker("Contact URL copied!"));
      })
      .catch((err) => {
        console.error("clipboard err", err);
        this.dialogService.openAlertDialog(
          marker("Copy Error"),
          marker("Could not copy to the clipboard")
        );
      });
  }

  public addContact() {
    this.serverRestApiService
      .mutate({
        query: createContactQuery,
        variables: {
          peerId: this.avatar.id,
        },
      })
      .then((res) => {
        this.dialogService.showSnackbar(
          marker("User added to your contact list.")
        );
      })
      .catch(() => {
        this.dialogService.openAlertDialog(
          marker("Error"),
          marker("Error happened during the operation.")
        );
      });
  }

  public goToDialog() {
    this.dialogueService
      .getData(this.avatar.id)
      .then((dialogueData) => {
        // there is already a dialogue for this user
        this.routerHandler.navigate([
          "room",
          this.avatar.id,
          "chat",
          "private",
        ]);
      })
      .catch((err) => {
        // we need to create a new dialogue
        this.dialogueService
          .createDialogue(this.avatar.id)
          .then((ok) => {
            this.routerHandler.navigate([
              "room",
              this.avatar.id,
              "chat",
              "private",
            ]);
          })
          .catch((err) => {
            this.dialogService.openAlertDialog(
              marker("Error"),
              marker("Error happened during the operation")
            );
          });
      });
  }

  @HostListener("document:click", ["$event"])
  private clickedOutside(event: MouseEvent) {
    if (
      this.menuFullyOpen &&
      !this.thisElementRef.nativeElement.contains(event.target)
    ) {
      this.menuTrigger.closeMenu();
      setTimeout(() => {
        this.menuFullyOpen = false;
      }, this.menuAnimationInMillis);
    }
  }

  private closeThenOpenMenu(avatar: AccountAvatarRecord): void {
    this.menuTrigger.closeMenu();

    setTimeout(() => {
      this.openMenu(avatar);
    }, this.menuAnimationInMillis);
  }

  private openMenu(avatar: AccountAvatarRecord): void {
    this.avatar = avatar;
    const { x, y } =
      this.originElementRef.nativeElement.getBoundingClientRect();
    const width = this.originElementRef.nativeElement.offsetWidth;
    this.left = x + this.marginRight + width + "px";
    this.top = y + "px";
    this.menuTrigger.openMenu();

    this.avatarRoomUrl = `/room/${avatar.id}/chat/private`;
    this.avatarInContacts = this.contactList.some(
      (contact) => contact.id == this.avatar.id
    );
    this.inCurrentRoom = this.avatarRoomUrl == this.router.url;

    setTimeout(() => {
      this.menuFullyOpen = true;
    }, this.menuAnimationInMillis);
  }
}
