import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { StaticObjectController } from '@objects-view/static-object-controller';
import {
  OperationDetailsOverviewComponent
} from '@shared/common-tabs/utilities/operations/operation-details-overview/operation-details-overview.component';
import { IOperationModel } from '@fleio-api/utils/model/operation.model';
import { IObjectStatus, StatusType, StatusValue } from '@objects-view/interfaces/object-status';
import { IObjectController } from '@objects-view/interfaces/object-controller';
import { LineDirection } from '@objects-view/status-line/status-line.component';
import { IAction } from '@objects-view/interfaces/actions/action';
import { ApiCallAction } from '@objects-view/actions/api-call-action';
import { OperationsApiService } from '@fleio-api/utils/operations/operations-api.service';

interface IOperationDisplay {
  operation: IOperationModel;
  status: IObjectStatus;
  objectController: IObjectController;
  expanded: boolean;
  actions: IAction[];
}

@Component({
  selector: 'app-activity-log-operations',
  templateUrl: './activity-log-operations.component.html',
  styleUrls: ['./activity-log-operations.component.scss']
})
export class ActivityLogOperationsComponent implements OnChanges, OnInit {
  @Input() indent: boolean = false;
  @Input() operations: IOperationModel[];
  operationsDisplay: IOperationDisplay[] = [];
  statusLineDirection = LineDirection.Vertical;

  constructor(private operationsApiService: OperationsApiService) {
  }

  getOperationObjectController(operation: IOperationModel) {
    return new StaticObjectController({
        header: {
          title: {
            text: null,
          }
        },
        tabs: [{
          tabName: $localize`Overview`,
          tabIdentifier: 'overview',
          component: OperationDetailsOverviewComponent,
        }],
        keepRefreshTimer: true,
      },
      operation,
    );
  }

  getOperationStatus(operation: IOperationModel): IObjectStatus {
    let status: IObjectStatus = {type: StatusType.None, value: StatusValue.None};
    if (operation.status === 'in progress') {
      status = {
        type: StatusType.Changing,
        value: StatusValue.Waiting
      };
    } else if (operation.status === 'succeeded') {
      status = {
        type: StatusType.Defined,
        value: StatusValue.Success
      };
    } else if (operation.status === 'failed') {
      status = {
        type: StatusType.Defined,
        value: StatusValue.Failed
      };
    } else if (operation.status === 'aborted') {
      status = {
        type: StatusType.Defined,
        value: StatusValue.Disabled
      };
    }
    return status;
  }

  getOperationActions(operation: IOperationModel): IAction[] {
    const actions: IAction[] = [];
    if (!operation.completed) {
      actions.push(new ApiCallAction(
        {
          object: operation,
          icon: {name: 'cancel'},
          tooltip: $localize`Abort operation`,
          name: $localize`Abort operation`,
          confirmOptions: {
            confirm: true,
            title: $localize`Abort operation`,
            message: $localize`Are you sure you want to abort operation ${operation.id}?`
          },
          apiService: this.operationsApiService,
          apiAction: 'abort_operation',
        }
      ));
    }
    if (operation.can_retry) {
      actions.push(new ApiCallAction(
        {
          object: operation,
          icon: {name: 'reboot', class: 'fl-icons'},
          tooltip: $localize`Retry`,
          name: $localize`Retry`,
          confirmOptions: {
            confirm: true,
            title: $localize`Retry operation`,
            message: $localize`Are you sure you want to retry operation ${operation.id}?`
          },
          apiService: this.operationsApiService,
          apiAction: 'retry',
        }
      ));
    }
    return actions;
  }


  updateOperationsDisplay() {
    const newOpsDisplay: IOperationDisplay[] = [];
    for (const operation of this.operations) {
      newOpsDisplay.push({
        operation: operation,
        objectController: this.getOperationObjectController(operation),
        status: this.getOperationStatus(operation),
        expanded: this.operationsDisplay.find(d => d.operation.id === operation.id)?.expanded || false,
        actions: this.getOperationActions(operation),
      })
    }

    this.operationsDisplay = newOpsDisplay;
  }

  ngOnInit() {
    this.updateOperationsDisplay();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes && changes.operations && changes.operations.previousValue) {
      this.updateOperationsDisplay();
    }
  }
}
