import { Component, ViewChild } from '@angular/core';
import { PageBase } from 'src/app/core/base/page-base';
import { ToastService } from 'src/app/service/toast.service';
import { ConfirmationDialogService } from 'src/app/service/confirmation-dialog.service';
import { ShortUrl } from 'src/app/model/entities/short-url';
import { ShortUrlsDataService } from 'src/app/modules/admin/short-urls/short-urls.data.service';
import { ShortUrlsColumns } from 'src/app/modules/admin/short-urls/short-urls.columns';
import { Filter } from 'src/app/model/graphql/filter/filter.model';
import QrCodeWithLogo from 'qrcode-with-logos';
import { FileUpload, FileUploadHandlerEvent } from 'primeng/fileupload';
import { ConfigService } from 'src/app/service/config.service';
import { ResolvedTableColumn } from 'src/app/modules/shared/components/table/table.model';
import { SidebarService } from 'src/app/service/sidebar.service';
import { takeUntil } from 'rxjs/operators';
import { Router } from '@angular/router';

@Component({
  selector: 'app-short-urls',
  templateUrl: './short-urls.page.html',
  styleUrl: './short-urls.page.scss',
})
export class ShortUrlsPage extends PageBase<
  ShortUrl,
  ShortUrlsDataService,
  ShortUrlsColumns
> {
  @ViewChild('imageUpload') imageUpload!: FileUpload;

  shortUrlsWithoutGroup: ShortUrl[] = [];
  groupedShortUrls: { [key: string]: ShortUrl[] } = {};

  qrCodeDialog: {
    visible: boolean;
    width: number;
    shortUrl: ShortUrl | undefined;
    qrCode: QrCodeWithLogo | undefined;
    logo: string | undefined;
  } = {
    visible: false,
    width: 512,
    shortUrl: undefined,
    qrCode: undefined,
    logo: undefined,
  };

  resolvedColumns: Map<string, ResolvedTableColumn<ShortUrl>[]> = new Map();

  get groupsFromGroupedShortUrls() {
    return Object.keys(this.groupedShortUrls);
  }

  private hide_deleted_filter: Filter = { deleted: { equal: false } };

  get showDeleted() {
    return !this.filter.some(
      f => JSON.stringify(f) === JSON.stringify(this.hide_deleted_filter)
    );
  }

  constructor(
    private toast: ToastService,
    private confirmation: ConfirmationDialogService,
    private config: ConfigService,
    private sidebar: SidebarService,
    private router: Router
  ) {
    super(true, {
      read: [],
      create: [],
      update: [],
      delete: [],
      restore: [],
    });

    this.sidebar.selectedUserSpace$
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe(() => {
        this.load(true);
      });
  }

  load(silent?: boolean): void {
    if (!silent) this.loading = true;
    this.dataService
      .load(this.filter, this.sort, this.skip, this.take)
      .subscribe(result => {
        this.result = result;
        this.shortUrlsWithoutGroup = this.getShortUrlsWithoutGroup();
        this.groupedShortUrls = this.getShortUrlsWithGroup();
        this.resolveColumns();
        this.loading = false;
      });
  }

  resolveColumns() {
    const columns = this.columns
      .map(x => {
        if (x.visible === undefined || x.visible === null) {
          x.visible = true;
        }
        return x;
      })
      .filter(x => !x.hidden && x.visible === true);

    if (!this.result.nodes || this.result.nodes.length == 0) {
      this.resolvedColumns = new Map();
      return;
    }

    this.result.nodes.forEach(row => {
      const resolvedRow: ResolvedTableColumn<ShortUrl>[] = [];
      columns.forEach(column => {
        resolvedRow.push({
          value: column.value(row),
          data: row,
          column: column,
        });
      });

      this.resolvedColumns.set(row.shortUrl, resolvedRow);
    });
  }

  delete(group: ShortUrl): void {
    this.confirmation.confirmDialog({
      header: 'dialog.delete.header',
      message: 'dialog.delete.message',
      accept: () => {
        this.loading = true;
        this.dataService.delete(group).subscribe(() => {
          this.toast.success('action.deleted');
          this.load();
        });
      },
      messageParams: { entity: group.shortUrl },
    });
  }

  restore(group: ShortUrl): void {
    this.confirmation.confirmDialog({
      header: 'dialog.restore.header',
      message: 'dialog.restore.message',
      accept: () => {
        this.loading = true;
        this.dataService.restore(group).subscribe(() => {
          this.toast.success('action.restored');
          this.load();
        });
      },
      messageParams: { entity: group.shortUrl },
    });
  }

  toggleShowDeleted() {
    if (!this.showDeleted) {
      this.filter.splice(this.filter.indexOf(this.hide_deleted_filter), 1);
    } else {
      this.filter.push(this.hide_deleted_filter);
    }

    this.load();
  }

  resetSort() {
    this.sort = [];
    this.load();
  }

  resetFilters() {
    this.filter = [];
    this.load();
  }

  qrDialog(shortUrl: ShortUrl) {
    this.qrCodeDialog.visible = true;
    this.qrCodeDialog.shortUrl = shortUrl;
    this.qrCodeDialog.width = 512;
    setTimeout(() => this.qr(), 100);
  }

  qrDialogClose() {
    this.qrCodeDialog.visible = false;
    this.qrCodeDialog.shortUrl = undefined;
    this.qrCodeDialog.qrCode = undefined;
  }

  qr() {
    if (!this.qrCodeDialog.shortUrl) return;

    const shortUrl = this.qrCodeDialog.shortUrl.shortUrl;
    const targetUrl = `${this.config.settings.api.redirector}/${shortUrl}`;

    this.qrCodeDialog.qrCode = new QrCodeWithLogo({
      content: targetUrl,
      width: this.qrCodeDialog.width,
      image: document.getElementById('qrCode') as HTMLImageElement,
      logo: this.qrCodeDialog.logo
        ? {
            src: this.qrCodeDialog.logo,
          }
        : undefined,
    });
  }

  async downloadQr() {
    if (!this.qrCodeDialog.qrCode || !this.qrCodeDialog.shortUrl) return;
    await this.qrCodeDialog.qrCode.downloadImage(
      `${this.qrCodeDialog.shortUrl?.shortUrl}.png`
    );
    this.qrCodeDialog.visible = false;
    this.qrCodeDialog.shortUrl = undefined;
  }

  logoUpload(event: FileUploadHandlerEvent) {
    if (!event.files || event.files.length === 0) return;

    this.qrCodeDialog.logo = URL.createObjectURL(event.files[0]);
    this.qr();
    this.imageUpload.clear();
  }

  open(url: string) {
    window.open(`${this.config.settings.api.redirector}/${url}`, '_blank');
  }

  copy(val: string) {
    navigator.clipboard
      .writeText(`${this.config.settings.api.redirector}/${val}`)
      .then(() => {
        this.toast.info('common.copied', 'common.copied_to_clipboard');
      });
  }

  getShortUrlsWithoutGroup(): ShortUrl[] {
    return this.result.nodes.filter(shortUrl => !shortUrl.group);
  }

  getShortUrlsWithGroup() {
    const groupedShortUrls: { [key: string]: ShortUrl[] } = {};

    this.result.nodes.forEach(shortUrl => {
      if (!shortUrl.group) return;

      const groupName = shortUrl.group.name;
      if (!groupedShortUrls[groupName]) {
        groupedShortUrls[groupName] = [];
      }
      groupedShortUrls[groupName].push(shortUrl);
    });

    return groupedShortUrls;
  }
}
