

import {ApiResult, ErrorResponse} from "helpers/api_request_builder";
import {MithrilViewComponent} from "jsx/mithril-component";
import m from "mithril";
import {Material} from "models/materials/types";
import * as Buttons from "views/components/buttons";
import {FlashMessage, MessageType} from "views/components/flash_message";
import {ConfigRepo} from "../../../models/config_repos/types";
import styles from "./test_connection.scss";

interface Attrs {
  configRepo?: ConfigRepo;
  material: Material;
  group?: string;
  pipeline?: string;

  // extra handlers will be fired in addition to defaults
  success?: (...args: any[]) => any;
  failure?: (err: ErrorResponse) => any;
  complete?: (...args: any[]) => any;
}

export class TestConnection extends MithrilViewComponent<Attrs> {
  private testConnectionMessage: m.Child | undefined;
  private testConnectionButtonIcon: string | undefined;
  private testConnectionButtonText: string = "Test Connection";
  private busy                             = false;

  private success?: (...args: any[]) => any;
  private failure?: ((err: ErrorResponse) => any);
  private complete?: (...args: any[]) => any;

  view(vnode: m.Vnode<Attrs>): m.Children | void | null {
    this.success  = vnode.attrs.success;
    this.failure  = vnode.attrs.failure;
    this.complete = vnode.attrs.complete;

    return <div class={styles.testConnectionButtonWrapper}>
      <Buttons.Secondary data-test-id="test-connection-button"
                         onclick={() => this.testConnection(vnode.attrs.material, vnode.attrs.pipeline, vnode.attrs.group, vnode.attrs.configRepo)} disabled={this.busy}>
        <span class={this.testConnectionButtonIcon} data-test-id="test-connection-icon"/>
        {this.testConnectionButtonText}
      </Buttons.Secondary>
      <div class={styles.testConnectionResult}>{this.testConnectionMessage}</div>
    </div>;
  }

  private testConnection(material: Material, pipelineName?: string, pipelineGroup?: string, configRepo?: ConfigRepo) {
    if (this.busy) { return; }

    if (configRepo && !configRepo.isValid()) {
      return Promise.resolve();
    }

    this.testConnectionInProgress();

    material.checkConnection(pipelineName, pipelineGroup, configRepo?.id()).then((result: ApiResult<any>) => {
      result.do(() => {
        this.testConnectionSuccessful();
        if (!!this.success) {
          this.success();
        }
      }, (err: ErrorResponse) => {
        this.testConnectionFailed(err);
        if (!!this.failure) {
          this.failure(err);
        }
      });
    }).finally(() => {
      this.testConnectionComplete();
      if (!!this.complete) {
        this.complete();
      }
    });
  }

  private testConnectionFailed(err: ErrorResponse) {
    this.testConnectionButtonIcon = styles.testConnectionFailure;
    this.testConnectionMessage    = <FlashMessage type={MessageType.alert} message={<pre>{JSON.parse(err.body!).message}</pre>}/>;
  }

  private testConnectionSuccessful() {
    this.testConnectionButtonIcon = styles.testConnectionSuccess;
    this.testConnectionMessage    = <FlashMessage type={MessageType.success} message="Connection OK"/>;
  }

  private testConnectionInProgress() {
    this.testConnectionButtonIcon = styles.testConnectionInProgress;
    this.testConnectionButtonText = "Testing Connection...";
    this.testConnectionMessage    = undefined;
    this.busy                     = true;
  }

  private testConnectionComplete() {
    this.testConnectionButtonText = "Test Connection";
    this.busy                     = false;
  }
}
