import { ObjectUIServiceBase } from '@objects-view/object-ui-service-base';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { IPermissionsModel } from '@fleio-api/base-model/IPermissionsModel';
import { IObjectStatus, StatusType, StatusValue } from '@objects-view/interfaces/object-status';
import { IIcon } from '@shared/ui/common/interfaces/icon';
import { ITitle } from '@objects-view/interfaces/card-data/card-title';
import { IAction } from '@objects-view/interfaces/actions/action';
import { RouterLinkAction } from '@objects-view/actions/router-link-action';
import { CallbackAction } from '@objects-view/actions/callback-action';
import { IDataField } from '@objects-view/interfaces/card-data/data-field';
import { IDetailsTab } from '@objects-view/interfaces/details/details-tab';
import { IClusterModel } from '@fleio-api/openstack/model/cluster.model';
import { ClustersApiService } from '@fleio-api/openstack/cluster/clusters-api.service';
import { ClusterDetailsInfoComponent } from '@shared/common-tabs/openstack/clusters/cluster-details-info/cluster-details-info.component';
import { ClusterDetailsNodesComponent } from '@shared/common-tabs/openstack/clusters/cluster-details-nodes/cluster-details-nodes.component';
import { ClusterDetailsMiscellaneousComponent } from '@shared/common-tabs/openstack/clusters/cluster-details-miscellaneous/cluster-details-miscellaneous.component';
import { ClusterDetailsLabelsComponent } from '@shared/common-tabs/openstack/clusters/cluster-details-labels/cluster-details-labels.component';
import { of } from 'rxjs';
import { ApiCallAction, CallType } from '@objects-view/actions/api-call-action';
import { ClusterResizeFormComponent } from '@shared/common-tabs/openstack/clusters/cluster-resize-form/cluster-resize-form.component';
import { ClusterCreateFormComponent } from '@shared/common-tabs/openstack/clusters/cluster-create-form/cluster-create-form.component';
import { ClusterUpgradeFormComponent } from '@shared/common-tabs/openstack/clusters/cluster-upgrade-form/cluster-upgrade-form.component';
import { map } from 'rxjs/operators';
import { MatDialog } from '@angular/material/dialog';
import { ClusterGetFileDialogComponent } from '@shared/common-dialogs/openstack/clusters/cluster-get-file-dialog/cluster-get-file-dialog.component';
import { ApiUsersApiService } from '@fleio-api/openstack/api-user/api-users-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { DateFormatterPipe } from '@shared/ui/common/pipes/date-formatter.pipe';

export class ClusterUiService extends ObjectUIServiceBase<IClusterModel> {
  private readonly router: Router;
  private readonly config: ConfigService;
  private readonly clustersApiService: ClustersApiService;
  private readonly datePipe: DateFormatterPipe;
  private matDialog: MatDialog;
  private apiUsersApiService: ApiUsersApiService;
  private notificationService: NotificationService;

  constructor(
    object: IClusterModel, permissions: IPermissionsModel, state: string,
    router: Router, config: ConfigService, clustersApiService: ClustersApiService, matDialog: MatDialog,
    apiUsersApiService: ApiUsersApiService, notificationService: NotificationService,
  ) {
    super(object, permissions, state);
    this.router = router;
    this.config = config;
    this.clustersApiService = clustersApiService;
    this.datePipe = new DateFormatterPipe(this.config);
    this.matDialog = matDialog;
    this.apiUsersApiService = apiUsersApiService;
    this.notificationService = notificationService;
  }

  getIcon(): IIcon {
    return null;
  }

  getStatus(): IObjectStatus {
    if (this.state === 'resize' || this.state === 'upgrade' || this.state === 'create') {
      return {type: StatusType.None, value: StatusValue.None};
    }
    if (this.object.under_task) {
      return {type: StatusType.Changing, value: StatusValue.Pending};
    } else {
      const status = this.object.status.toUpperCase();
      if (['CREATE_COMPLETE', 'UPDATE_COMPLETE', 'RESUME_COMPLETE', 'RESTORE_COMPLETE', 'ROLLBACK_COMPLETE',
        'SNAPSHOT_COMPLETE', 'CHECK_COMPLETE', 'ADOPT_COMPLETE'].indexOf(status) > -1) {
        return {type: StatusType.Defined, value: StatusValue.Active};
      } else if (['CREATE_FAILED', 'UPDATE_FAILED', 'DELETE_FAILED', 'ROLLBACK_FAILED',
        'RESUME_FAILED'].indexOf(status) > -1) {
        return {type: StatusType.Defined, value: StatusValue.Error};
      } else {
        return {type: StatusType.Defined, value: StatusValue.Pending};
      }
    }
  }

  getTitle(): ITitle {
    switch (this.state) {
      case 'create':
        return {
          text: $localize`Create cluster`
        };
      case 'resize':
        let objTitle: string;
        if (this.object.name) {
          objTitle = this.object.name;
        } else {
          objTitle = this.object.id as string;
        }
        return {
          text: $localize`Resize ${objTitle}`
        };
      case 'upgrade':
        let objTitleUpgrade: string;
        if (this.object.name) {
          objTitleUpgrade = this.object.name;
        } else {
          objTitleUpgrade = this.object.id as string;
        }
        return {
          text: $localize`Upgrade ${objTitleUpgrade}`
        };
      default:
        let title: string;
        if (this.object.name) {
          title = this.object.name;
        } else {
          title = this.object.id as string;
        }
        return {
          text: title,
          subText: this.object.display_status,
        };
    }
  }

  getActions(): IAction[] {
    return [
      new RouterLinkAction({
        name: $localize`Resize`,
        tooltip: $localize`Resize`,
        icon: {name: 'resize', class: 'fl-icons'},
        router: this.router,
        routerUrl: this.config.getPanelUrl(`openstack/clusters/${this.object.id}/resize`),
        noPermissions: !this.permissions['clusters.resize'],
      }),
      new RouterLinkAction({
        name: $localize`Upgrade`,
        tooltip: $localize`Upgrade`,
        icon: {name: 'arrow_circle_up'},
        router: this.router,
        routerUrl: this.config.getPanelUrl(`openstack/clusters/${this.object.id}/upgrade`),
        noPermissions: !this.permissions['clusters.upgrade'],
      }),
      new CallbackAction({
        object: this.object,
        tooltip: $localize`Get configuration`,
        icon: {name: 'file_copy'},
        name: $localize`Get configuration`,
        noPermissions: !this.permissions['clusters.get_configuration'],
        callback: () => {
          this.apiUsersApiService.list().subscribe(response => {
            if (!response.objects || !response.objects.length) {
              this.notificationService.showMessage($localize`No OpenStack api users found.`);
            } else {
              return this.matDialog.open(
                ClusterGetFileDialogComponent, {
                  data: {
                    type: 'configuration',
                    cluster: this.object,
                    apiUsers: response.objects,
                  },
                  autoFocus: false,
                }).afterClosed().pipe(map(result => {
                if (result === true) {
                  return {message: $localize`Got configuration`};
                } else {
                  return {message: null};
                }
              }));
            }
          }, error => {
            this.notificationService.showMessage($localize`Could not find OpenStack api user to authenticate with.`);
          });
          return of(null);
        }
      }),
      new CallbackAction({
        object: this.object,
        tooltip: $localize`Get certificate`,
        icon: {name: 'description'},
        name: $localize`Get certificate`,
        noPermissions: !this.permissions['clusters.get_certificate'],
        callback: () => {
          this.apiUsersApiService.list().subscribe(response => {
            if (!response.objects || !response.objects.length) {
              this.notificationService.showMessage($localize`No OpenStack api users found.`);
            } else {
              return this.matDialog.open(
                ClusterGetFileDialogComponent, {
                  data: {
                    type: 'certificate',
                    cluster: this.object,
                    apiUsers: response.objects,
                  },
                  autoFocus: false,
                }).afterClosed().pipe(map(result => {
                if (result === true) {
                  return {message: $localize`Got certificate`};
                } else {
                  return {message: null};
                }
              }));
            }
          }, error => {
            this.notificationService.showMessage($localize`Could not find OpenStack api user to authenticate with.`);
          });
          return of(null);
        }
      }),
      new ApiCallAction({
        object: this.object,
        icon: {name: 'delete'},
        tooltip: $localize`Delete cluster`,
        name: $localize`Delete`,
        noPermissions: !this.permissions['clusters.destroy'],
        confirmOptions: {
          confirm: true,
          title: $localize`Delete cluster ${this.object.name || this.object.id}`,
          message: null,
          importantMessage: $localize`Are you sure you want to delete the cluster? Data will be permanently lost.`,
        },
        successMessage: $localize`Cluster delete queued`,
        errorMessage: $localize`Failed to delete cluster, check logs for details`,
        apiService: this.clustersApiService,
        callType: CallType.Delete,
        refreshAfterExecute: false,
        redirectAfterExecute: true,
        redirectUrl: this.config.getPanelUrl('openstack/clusters'),
      })
    ];
  }

  getDetailsActions(): IAction[] {
    const actions = [];

    switch (this.state) {
      case 'create':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`openstack/clusters`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Create`}));
        break;
      case 'resize':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`openstack/clusters`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Resize`}));
        break;
      case 'upgrade':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`openstack/clusters`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Upgrade`}));
        break;
      default:
        break;
    }

    return actions;
  }

  getDetailsLink(): string {
    return this.config.getPanelUrl(`openstack/clusters/${this.object.id}`);
  }

  getCardFields(): IDataField[] {
    return [
      {
        name: $localize`ID`,
        value: this.object.id,
      },
      {
        name: $localize`Region`,
        value: this.object.region,
      },
    ] as Array<IDataField>;
  }

  getTabs(): IDetailsTab[] {
    switch (this.state) {
      case 'details':
        return [
          {
            component: ClusterDetailsInfoComponent,
            tabName: $localize`Info`,
            tabIdentifier: 'info',
          },
          {
            component: ClusterDetailsNodesComponent,
            tabName: $localize`Nodes`,
            tabIdentifier: 'nodes',
          },
          {
            component: ClusterDetailsMiscellaneousComponent,
            tabName: $localize`Miscellaneous`,
            tabIdentifier: 'miscellaneous',
          },
          {
            component: ClusterDetailsLabelsComponent,
            tabName: $localize`Labels`,
            tabIdentifier: 'labels',
          }
        ];
      case 'resize':
        return [
          {
            component: ClusterResizeFormComponent,
            tabName: $localize`Resize`,
            tabIdentifier: 'resize',
          }
        ];
      case 'upgrade':
        return [
          {
            component: ClusterUpgradeFormComponent,
            tabName: $localize`Upgrade`,
            tabIdentifier: 'upgrade',
          }
        ];
      case 'create':
        return [
          {
            component: ClusterCreateFormComponent,
            tabName: $localize`Create`,
            tabIdentifier: 'create',
          }
        ];
      default:
        return [];
    }
  }

  getCardTags(): string[] {
    const tags = [];
    return tags;
  }
}
