import { ChangeDetectorRef, Component, NgZone, OnInit } from '@angular/core';
import { DetailsComponentBase } from '@objects-view/details-component-base';
import { IInstanceModel } from '@fleio-api/openstack/model/instance.model';
import { ImagesApiService } from '@fleio-api/openstack/image/image-api.service';
import { IImageModel } from '@fleio-api/openstack/model/image.model';
import { MatDialog } from '@angular/material/dialog';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import {
  InstanceDetailsCreateSnapshotDialogComponent
} from '@shared/common-dialogs/openstack/instances/instance-details-create-snapshot-dialog/instance-details-create-snapshot-dialog.component';
import { NotificationService } from '@shared/ui-api/notification.service';
import { ConfigService } from '@shared/config/config.service';
import { IAction } from '@objects-view/interfaces/actions/action';
import { CallbackAction } from '@objects-view/actions/callback-action';
import { ApiCallAction, CallType } from '@objects-view/actions/api-call-action';
import { RouterLinkAction } from '@objects-view/actions/router-link-action';
import { Router } from '@angular/router';
import { of } from 'rxjs';

export interface IGetSnapshotsForInstanceResponse {
  objects: IImageModel[];
  volume_snapshots_count: number;
}

@Component({
  selector: 'app-instance-details-snapshots',
  templateUrl: './instance-details-snapshots.component.html',
  styleUrls: ['./instance-details-snapshots.component.scss']
})
export class InstanceDetailsSnapshotsComponent extends DetailsComponentBase<IInstanceModel> implements OnInit {
  snapshots: IImageModel[];
  volumeSnapshotsCount = 0;
  loading = null;
  displayedColumns: string[];
  permissions: Record<string, unknown>;
  snapshotActions = {};

  constructor(
    private notificationService: NotificationService,
    private imagesApiService: ImagesApiService,
    private router: Router,
    private matDialog: MatDialog,
    public config: ConfigService,
    ngZone: NgZone,
    changeDetectorRef: ChangeDetectorRef,
  ) {
    super(ngZone, changeDetectorRef, config);
  }

  private getSnapshotActions(snapshot: any): IAction[] {
    const actions: IAction[] = [];
    actions.push(
      new RouterLinkAction({
          icon: {name: 'edit', class: 'fl-icons'},
          name: $localize`Edit`,
          tooltip: $localize`Edit`,
          routerUrl: this.config.getPanelUrl(
            `openstack/images/${snapshot.id}/edit`,
          ),
          router: this.router,
        }
      ));

    let launchUrl = `openstack/instances/create?image_id=${snapshot.id}&region=${snapshot.region}`;
    if (snapshot.client?.id) {
      launchUrl += `&client_id=${snapshot.client.id}`;
    }

    actions.push(
      new RouterLinkAction({
          icon: {name: 'launch', class: 'fl-icons'},
          name: $localize`Launch`,
          tooltip: $localize`Launch image`,
          routerUrl: this.config.getPanelUrl(launchUrl),
          router: this.router,
        }
      ));
    actions.push(
      new RouterLinkAction({
          icon: {name: 'rebuild', class: 'fl-icons'},
          name: $localize`Rebuild current instance`,
          tooltip: $localize`Rebuild current instance`,
          routerUrl: this.config.getPanelUrl(
            `openstack/instances/${this.object.id}/rebuild?image_id=${snapshot.id}`,
          ),
          router: this.router,
        }
      ));
    actions.push(
      new CallbackAction(
        {
          object: snapshot,
          tooltip: $localize`Download image`,
          icon: {name: 'cloud_download'},
          name: $localize`Download image`,
          featureName: 'openstack.images.download',
          callback: () => {
            this.config.authService.generateOtpToken().subscribe(token => {
              const url = this.config.getPanelApiUrl(
                `openstack/images/${snapshot.id}/download?fleio-token=${token}`,
              );
              window.location.href = url;
            });
            return of(null);
          },
        }
      ));
    actions.push(
      new ApiCallAction(
        {
          object: snapshot,
          icon: {name: 'delete'},
          name: $localize`Delete`,
          tooltip: $localize`Delete image`,
          confirmOptions: {
            confirm: true,
            title: $localize`Delete image`,
            message: $localize`Are you sure you want to delete image ${snapshot.name}?`,
          },
          successMessage: $localize`Image delete queued`,
          errorMessage: $localize`Failed to delete image, check logs for details`,
          apiService: this.imagesApiService,
          callType: CallType.Delete,
          refreshAfterExecute: true,
          redirectAfterExecute: false,
          redirectUrl: this.config.getPanelUrl('openstack/images'),
        }
      ));

    return actions;
  }

  private loadSnapshots() {
    if (this.loading === null) {
      // show loading only the first time
      this.loading = true;
    }
    this.imagesApiService.getSnapshotsForInstance(this.object.id).pipe().subscribe(
      (response: IGetSnapshotsForInstanceResponse) => {
        this.snapshots = response.objects;
        for (const snapshot of this.snapshots) {
          this.snapshotActions[snapshot.id] = this.getSnapshotActions(snapshot);
        }
        this.volumeSnapshotsCount = response.volume_snapshots_count;
        this.loading = false;
      });
  }

  public openCreateSnapshotDialog() {
    return this.matDialog.open(
      InstanceDetailsCreateSnapshotDialogComponent, {
        data: {
          instanceId: this.object.id,
          instanceName: this.object.name
        },
        autoFocus: false,
      }).afterClosed().pipe().subscribe(result => {
      if (result === false || typeof result === 'undefined') {
        return;
      }
      this.notificationService.showMessage($localize`Snapshot scheduled for creation.`);
      this.boostRefreshTimer();
      return {message: result} as IActionResult;
    });
  }

  public readableBytes(bytes: number | null) {
    if (bytes === null) {
      return $localize`Size info not available`;
    }
    if (bytes === 0) {
      return $localize`0 bytes`;
    }
    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    const sizes = ['B', 'KB', 'MB', 'GB'];
    // @ts-ignore
    return (bytes / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + sizes[i];
  }

  protected refreshData() {
    this.loadSnapshots();
  }

  allowedAction(action: string) {
    return this.object.allowed_actions.indexOf(action) > -1;
  }

  ngOnInit() {
    super.ngOnInit();
    this.displayedColumns = ['name', 'status', 'size', 'created_at'];
    if (this.config.authService.feature('ui.openstack.instances.snapshots.display_client')) {
      this.displayedColumns.push('client');
    }
    this.displayedColumns.push('(actions)');
    if (this.objectController) {
      this.permissions = this.objectController.additionalObjects.permissions;
    }
  }
}
