import { ChangeDetectorRef, Component, OnInit, ViewChild, ViewChildren } from '@angular/core';
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import {
  getNanoBundleLicensesQuery,
  getNanoLicensesQuery,
  getRecurringOrdersQuery,
  redeemLicenseTokenQuery,
} from 'src/app/shared/server-services/querys';
import { ServerRestApiService } from 'src/app/shared/services/server-rest-api.service';
import { TitleService } from 'src/app/shared/services/title.service';
import {
  LicenseBundleRecord,
  LicenseRecord,
  RecurringOrderRecord,
} from 'src/app/shared/server-services/query-records/nano-records';
import { MatDialog } from '@angular/material/dialog';
import { BundledLicensesDialogComponent } from './bundled-licenses-dialog/bundled-licenses-dialog.component';
import { RedeemTokenDialogComponent } from './redeem-token-dialog/redeem-token-dialog.component';
import { RecurringOrderDetailDialogComponent } from './recurring-order-detail-dialog/recurring-order-detail-dialog.component';
import { DialogService } from 'src/app/shared/services/dialog.service';
import { MatTable } from '@angular/material/table';
import { CordovaService } from 'src/app/shared/services/cordova.service';

import { environment } from 'src/environments/environment';
import { BlobService } from 'src/app/shared/services/blob.service';
import { SnackBarService } from 'src/app/shared/services/snackbar.service';
import { sideMenuActiveObserver } from 'src/app/shared/shared-observers';

@Component({
  selector: 'app-nano-license',
  templateUrl: './nano-license.component.html',
  styleUrls: ['./nano-license.component.scss'],
})
export class NanoLicenseComponent implements OnInit {
  licenseColumns: string[] = ['id', 'number', 'expiration', 'recurrence', 'revoked'];
  bundleColumns: string[] = ['id', 'number', 'expiration', 'months', 'revoked', 'action'];
  licenses: LicenseRecord[];
  bundles: LicenseBundleRecord[];
  recurringOrders: RecurringOrderRecord[];
  loading: boolean = false;
  isOnApp: boolean = false;
  licenseUrl: string = environment.site_base + '/license-buy';

  @ViewChild('licenseTable', { static: false }) licenseTable: MatTable<any>;

  constructor(
    private serverRestApi: ServerRestApiService,
    private titleService: TitleService,
    private dialog: MatDialog,
    private dialogService: DialogService,
    private changeDetectorRef: ChangeDetectorRef,
    private cordovaService: CordovaService,
    private blobService: BlobService,
    private snackbarService: SnackBarService
  ) {
    this.titleService.setTabTitle(marker('Licenses'));
    this.isOnApp = this.cordovaService.isOnApp();
  }

  ngOnInit() {
    sideMenuActiveObserver.next(false);
    this.getLicense();
  }

  public openBuyLicenseInBrowser() {
    this.cordovaService.openLinkInBrowser(this.licenseUrl);
  }

  public getLicense() {
    this.serverRestApi.query({ query: getNanoLicensesQuery }).then((res) => {
      this.licenses = res.licenses;
      this.bundles = res.bundles;

      this.serverRestApi.query({ query: getRecurringOrdersQuery }).then((res) => {
        this.recurringOrders = res.response;

        for (let recurringOrder of this.recurringOrders) {
          var license = this.licenses.find((l) => l.id == recurringOrder.license_id);
          if (license) {
            license.recurringOrder = recurringOrder;
          }
        }
      });

      this.sortLicensesAndBundles();

      this.changeDetectorRef.detectChanges();
      if (this.licenses.length > 0) this.licenseTable.renderRows();
    });
  }

  public isExpired(license) {
    return new Date(license.expiration * 1000) < new Date();
  }

  public showBundleLicenses(bundle: LicenseBundleRecord) {
    if (this.loading) return;

    this.loading = true;

    this.getTokens(bundle.id).then((res) => {
      var dialogRef = this.dialog.open(BundledLicensesDialogComponent, { data: res });
      this.loading = false;
    });
  }

  public downloadBundleLicenses(bundle: LicenseBundleRecord) {
    if (this.loading) return;

    this.loading = true;

    this.getTokens(bundle.id)
      .then((res) => {
        var tokensString = (<string[]>res.tokens).join(',\r\n');
        const blob = this.blobService.new([tokensString]); //  { type: 'text/csv' }
        const url = this.blobService.createObjectURL(blob);
        var a;
        a = document.createElement('a');
        a.href = url;
        a.download = `CBNANO-BUNDLED-LICENSES-${bundle.id}.csv`;
        a.click();
      })
      .finally(() => (this.loading = false));
  }

  public showRedeemDialog(): void {
    var dialogRef = this.dialog.open(RedeemTokenDialogComponent);
    dialogRef.afterClosed().subscribe((tokenString: string) => {
      if (!tokenString) return;

      this.serverRestApi
        .mutate({ query: redeemLicenseTokenQuery, variables: { licenseToken: tokenString.trim() } })
        .then(() => {
          this.snackbarService.showSnackbar(marker('Token successfully redeemed!'));
          this.getLicense();
        })
        .catch((err) => {
          console.error(err);
          this.dialogService.openAlertDialog(
            marker('Invalid token'),
            marker('Could not redeem token. Please make sure you are using a valid, unused token.')
          );
        });
    });
  }

  public openRecurringOrderDetail(recurringOrder: RecurringOrderRecord): void {
    var dialogRef = this.dialog.open(RecurringOrderDetailDialogComponent, { data: recurringOrder });
    dialogRef.afterClosed().subscribe((canceled: boolean) => {
      if (canceled) this.getLicense();
    });
  }

  private getTokens(bundleId: string): Promise<any> {
    return this.serverRestApi.query({
      query: getNanoBundleLicensesQuery,
      variables: { id: bundleId },
    });
  }

  private sortLicensesAndBundles() {
    this.licenses.sort(this.sortFn);
    this.bundles.sort(this.sortFn);
  }
  private sortFn = (a, b) => {
    if (a.revoked || b.revoked || this.isExpired(a) || this.isExpired(b)) {
      if (a.revoked) return 1;
      if (b.revoked) return -1;
      if (this.isExpired(a)) return 1;
      if (this.isExpired(b)) return -1;
    } else {
      return a.expiration - b.expiration;
    }
  };
}
