/*
 * 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.
 */

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Rest } from '@submarine/interfaces';
import { ExperimentInfo } from '@submarine/interfaces/experiment-info';
import { ExperimentSpec } from '@submarine/interfaces/experiment-spec';
import { ExperimentTemplate } from '@submarine/interfaces/experiment-template';
import { ExperimentTemplateSubmit } from '@submarine/interfaces/experiment-template-submit';
import { BaseApiService } from '@submarine/services/base-api.service';
import { of, throwError, Observable, Subject } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class ExperimentService {
  /*
    communicate between route-outlet and parent
    send experiment-id from ExperimentInfo to ExperimentHome
  */
  private emitInfoSource = new Subject<string>();
  infoEmitted$ = this.emitInfoSource.asObservable();

  constructor(private baseApi: BaseApiService, private httpClient: HttpClient) {}

  emitInfo(id: string) {
    this.emitInfoSource.next(id);
  }

  fetchExperimentList(): Observable<ExperimentInfo[]> {
    const apiUrl = this.baseApi.getRestApi('/v1/experiment');
    return this.httpClient.get<Rest<ExperimentInfo[]>>(apiUrl).pipe(
      switchMap((res) => {
        if (res.success) {
          return of(res.result);
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'get');
        }
      })
    );
  }

  querySpecificExperiment(id: string): Observable<ExperimentInfo> {
    const apiUrl = this.baseApi.getRestApi('/v1/experiment/' + id);
    return this.httpClient.get<Rest<ExperimentInfo>>(apiUrl).pipe(
      switchMap((res) => {
        if (res.success) {
          return of(res.result);
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'get');
        }
      })
    );
  }

  createExperiment(experimentSpec: ExperimentSpec): Observable<ExperimentInfo> {
    const apiUrl = this.baseApi.getRestApi('/v1/experiment');
    return this.httpClient.post<Rest<ExperimentInfo>>(apiUrl, experimentSpec).pipe(
      map((res) => res.result), // return result directly if succeeding
      catchError((e) => {
        let message: string;
        if (e.error instanceof ErrorEvent) {
          // client side error
          message = 'Something went wrong with network or workbench';
        } else {
          console.log(e);
          if (e.status === 409) {
            message = 'You might have a duplicate experiment name';
          } else if (e.status >= 500) {
            message = `${e.message}`;
          } else {
            message = e.error.message;
          }
        }
        return throwError(message);
      })
    );
  }

  updateExperiment(id: string, experimentSpec: ExperimentSpec): Observable<ExperimentInfo> {
    const apiUrl = this.baseApi.getRestApi(`/v1/experiment/${id}`);
    return this.httpClient.patch<Rest<ExperimentInfo>>(apiUrl, experimentSpec).pipe(
      map((res) => res.result),
      catchError((e) => {
        console.log(e);
        let message: string;
        if (e.error instanceof ErrorEvent) {
          // client side error
          message = 'Something went wrong with network or workbench';
        } else {
          if (e.status === 409) {
            message = 'You might have a duplicate experiment name';
          } else if (e.status >= 500) {
            message = `${e.message}`;
          } else {
            message = e.error.message;
          }
        }
        return throwError(message);
      })
    );
  }

  deleteExperiment(id: string): Observable<ExperimentInfo> {
    const apiUrl = this.baseApi.getRestApi(`/v1/experiment/${id}`);
    return this.httpClient.delete<Rest<any>>(apiUrl).pipe(
      switchMap((res) => {
        if (res.success) {
          return of(res.result);
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'delete', id);
        }
      })
    );
  }

  getExperimentLog(id: string): Observable<any> {
    const apiUrl = this.baseApi.getRestApi('/v1/experiment/logs/' + id);
    return this.httpClient.get<Rest<any>>(apiUrl).pipe(
      switchMap((res) => {
        if (res.success) {
          return of(res.result);
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'get', id);
        }
      })
    );
  }

  getExperimentParam(param: object): Observable<any> {
    const apiUrl = this.baseApi.getRestApi('/param/selective');
    return this.httpClient.post<any>(apiUrl, param).pipe(
      switchMap((res) => {
        if (res.success) {
          return of(res.result);
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'post', param);
        }
      })
    );
  }

  getExperimentMetric(param: object): Observable<any> {
    const apiUrl = this.baseApi.getRestApi('/metric/selective');
    return this.httpClient.post<any>(apiUrl, param).pipe(
      switchMap((res) => {
        if (res.success) {
          return of(res.result);
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'post', param);
        }
      })
    );
  }

  fetchExperimentTemplateList(): Observable<ExperimentTemplate[]> {
    const apiUrl = this.baseApi.getRestApi('/v1/template');
    return this.httpClient.get<Rest<ExperimentTemplate[]>>(apiUrl).pipe(
      map((res) => {
        if (res.success) {
          return res.result;
        } else {
          throw this.baseApi.createRequestError(res.message, res.code, apiUrl, 'get');
        }
      })
    );
  }

  createExperimentfromTemplate(
    experimentSpec: ExperimentTemplateSubmit,
    templateName: string
  ): Observable<ExperimentInfo> {
    const apiUrl = this.baseApi.getRestApi(`/v1/experiment/${templateName}`);
    return this.httpClient.post<Rest<ExperimentInfo>>(apiUrl, experimentSpec).pipe(
      map((res) => res.result),
      catchError((e) => {
        let message: string;
        if (e.error instanceof ErrorEvent) {
          // client side error
          message = 'Something went wrong with network or workbench';
        } else {
          console.log(e);
          if (e.status === 409) {
            message = 'You might have a duplicate experiment name';
          } else if (e.status >= 500) {
            message = `${e.message}`;
          } else {
            message = e.error.message;
          }
        }
        return throwError(message);
      })
    );
  }

  durationHandle(secs: number) {
    const hr = Math.floor(secs / 3600);
    const min = Math.floor((secs - hr * 3600) / 60);
    const sec = Math.round(secs) - hr * 3600 - min * 60;
    let showHr;
    let showMin;
    let showSec;
    if (hr < 10) {
      showHr = '0' + hr;
    } else {
      showHr = hr.toString();
    }
    if (min < 10) {
      showMin = '0' + min;
    } else {
      showMin = min.toString();
    }
    if (sec < 10) {
      showSec = '0' + sec;
    } else {
      showSec = sec.toString();
    }
    return `${showHr}:${showMin}:${showSec}`;
  }
}
