/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/* tslint:disable:no-empty */

import { Observable } from 'rxjs';

import { ConfirmationDialogType } from './confirmation-dialog-type.enum';
import { UserResourceService, HealthStatusService, ManageEnvironmentsService } from '../../../core/services';

export class ConfirmationDialogModel {
  public title: string;
  public notebook: any;
  public confirmAction: Function;
  private manageAction: Function;
  private userResourceService: UserResourceService;
  private healthStatusService: HealthStatusService;
  private manageEnvironmentsService: ManageEnvironmentsService;

  static getDefault(): ConfirmationDialogModel {
    return new ConfirmationDialogModel(
      ConfirmationDialogType.StopExploratory, { name: '', resources: [] }, () => { }, () => { }, false, null, null, null);
  }

  constructor(
    confirmationType: ConfirmationDialogType,
    notebook: any,
    fnProcessResults: any,
    fnProcessErrors: any,
    manageAction,
    userResourceService: UserResourceService,
    healthStatusService: HealthStatusService,
    manageEnvironmentsService: ManageEnvironmentsService
  ) {
    this.userResourceService = userResourceService;
    this.healthStatusService = healthStatusService;
    this.manageEnvironmentsService = manageEnvironmentsService;
    this.manageAction = manageAction;
    this.setup(confirmationType, notebook, fnProcessResults, fnProcessErrors);
  }

  public isAliveResources(resources): boolean {
    if (resources) {
      for (let i = 0; i < resources.length; i++) {
        if (resources[i].status.toLowerCase() !== 'failed'
          && resources[i].status.toLowerCase() !== 'terminated'
          && resources[i].status.toLowerCase() !== 'terminating'
          && resources[i].status.toLowerCase() !== 'stopped')
          return true;
      }
    }

    return false;
  }


  private stopExploratory(): Observable<{}> {
    return this.manageAction
      ? this.manageEnvironmentsService.environmentManagement(this.notebook.user, 'stop', this.notebook.project, this.notebook.name)
      : this.userResourceService.suspendExploratoryEnvironment(this.notebook, 'stop');
  }

  private terminateExploratory(): Observable<{}> {
    return this.manageAction ? this.manageEnvironmentsService.environmentManagement(
        this.notebook.user, 'terminate', this.notebook.project,  this.notebook.name
      ) : this.userResourceService.suspendExploratoryEnvironment(this.notebook, 'terminate');
  }

  private stopEdgeNode(): Observable<{}> {
    return this.manageAction
      ? this.manageEnvironmentsService.environmentManagement(this.notebook.user, 'stop', this.notebook.project, 'edge')
      : this.healthStatusService.suspendEdgeNode();
  }

  private setup(confirmationType: ConfirmationDialogType, notebook: any, fnProcessResults: any, fnProcessErrors: any): void {
    const defaultStopMessage = 'Notebook server will be stopped.';
    const containRunningResourcesStopMessage = 'Notebook server will be stopped and all computational resources will be stopped/terminated.';

    const defaultTerminateMessage = 'Notebook server will be terminated.';
    const containRunningResourcesTerminateMessage = 'Notebook server and all computational resources will be terminated.';

    const edgeNodeStopMessage = 'Edge node will be stopped. You will need to start it later to proceed working with project.';

    switch (confirmationType) {
      case ConfirmationDialogType.StopExploratory: {
        this.title = this.isAliveResources(notebook.resources) ? containRunningResourcesStopMessage : defaultStopMessage;
        this.notebook = notebook;
        this.confirmAction = () => this.stopExploratory()
          .subscribe(
            response => fnProcessResults(response),
            error => fnProcessErrors(error));
      }
        break;
      case ConfirmationDialogType.TerminateExploratory: {
        this.title = this.isAliveResources(notebook.resources) ? containRunningResourcesTerminateMessage : defaultTerminateMessage;
        this.notebook = notebook;
        this.confirmAction = () => this.terminateExploratory()
          .subscribe(
            response => fnProcessResults(response),
            error => fnProcessErrors(error));
      }
        break;
      case ConfirmationDialogType.StopEdgeNode: {
        this.title = edgeNodeStopMessage;
        this.notebook = notebook;
        this.confirmAction = () => this.stopEdgeNode()
          .subscribe(
            response => fnProcessResults(response),
            error => fnProcessErrors(error));
      }
        break;
      default: {
        this.title = this.isAliveResources(notebook.resources) ? containRunningResourcesTerminateMessage : defaultTerminateMessage;
        this.notebook = notebook;
        this.confirmAction = () => this.stopExploratory()
          .subscribe(
            response => fnProcessResults(response),
            error => fnProcessErrors(error));
      }
        break;
    }
  }
}
