/*
 * 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 { Component, OnInit, Inject } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { map } from 'rxjs/operators';

import { EndpointService } from '../../../core/services';
import { NotificationDialogComponent } from '../../../shared/modal-dialog/notification-dialog';
import { PATTERNS } from '../../../core/util';

export interface Endpoint {
  name: string;
  url: string;
  account: string;
}

@Component({
  selector: 'endpoints',
  templateUrl: './endpoints.component.html',
  styleUrls: ['./endpoints.component.scss']
})
export class EndpointsComponent implements OnInit {
  public createEndpointForm: FormGroup;
  public maxEndpointNameLength: number = 6;
  endpoints: Endpoint[] = [];
  displayedColumns: string[] = ['name', 'url', 'account', 'endpoint_tag', 'actions'];

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: any,
    public toastr: ToastrService,
    public dialogRef: MatDialogRef<EndpointsComponent>,
    public dialog: MatDialog,
    private endpointService: EndpointService,
    private _fb: FormBuilder,
  ) { }

  ngOnInit() {
    this.initFormModel();
    this.getEndpointList();
  }

  public generateEndpointTag($event) {
    this.createEndpointForm.controls.endpoint_tag.setValue($event.target.value.toLowerCase());
  }

  public assignChanges(data) {
    this.endpointService.createEndpoint(data).subscribe(() => {
      this.toastr.success('Endpoint connected successfully!', 'Success!');
      this.dialogRef.close(true);
    }, error => this.toastr.error(error.message || 'Endpoint connection failed!', 'Oops!'));
  }

  public deleteEndpoint(data): void {
    this.endpointService.getEndpointsResource(data.name)
      .pipe(
        map(resource =>
          resource.projects
            .map(project =>
              EndpointsComponent.createResourceList(
                project.name,
                resource.exploratories.filter(notebook => notebook.project === project.name),
                project.endpoints.filter(endpoint => endpoint.name === data.name)[0].status)
            )
            .filter(project => project.nodeStatus !== 'TERMINATED'
              && project.nodeStatus !== 'TERMINATING'
              && project.nodeStatus !== 'FAILED'
            )
        )
      )
      .subscribe((resource: any) => {
        this.dialog.open(NotificationDialogComponent, {
          data: {
            type: 'confirmation', item: data, list: resource
          }, panelClass: 'modal-sm'
        })
          .afterClosed().subscribe(result => {
            result && this.deleteEndpointOption(data);
          });
      });
  }

  public getEndpoinConnectionStatus(url) {
    const getStatus = this.endpointService.getEndpoinConnectionStatus(encodeURIComponent(url));
    this.dialog.open(EndpointTestResultDialogComponent, { data: { url: url, getStatus }, panelClass: 'modal-sm' });
  }

  private static createResourceList(name: string, resource: Array<any>, nodeStatus: string): Object {
    return { name, resource, nodeStatus };
  }

  private initFormModel(): void {
    this.createEndpointForm = this._fb.group({
      name: ['', Validators.compose([
        Validators.required, 
        Validators.pattern(PATTERNS.namePattern), 
        this.validateName.bind(this), 
        this.providerMaxLength.bind(this)
      ])],
      url: ['', Validators.compose([
        Validators.required, 
        Validators.pattern(PATTERNS.fullUrl), 
        this.validateUrl.bind(this)
      ])],
      account: ['', Validators.compose([
        Validators.required, 
        Validators.pattern(PATTERNS.namePattern)
      ])],
      endpoint_tag: ['', Validators.compose([
        Validators.required, 
        Validators.pattern(PATTERNS.namePattern)
      ])]
    });
  }

  private deleteEndpointOption(data): void {
    this.endpointService.deleteEndpoint(`${data.name}`)
      .subscribe(
        () => {
          this.toastr.success('Endpoint successfully disconnected. All related resources are terminating!', 'Success!');
          this.getEndpointList();
        }, 
        error => this.toastr.error(error.message || 'Endpoint creation failed!', 'Oops!')
      );
  }

  private getEndpointList(): void {
    this.endpointService.getEndpointsData().subscribe((endpoints: any) => this.endpoints = endpoints);
  }

  private validateUrl(control) {
    if (control && control.value) {
      const isDublicat = this.endpoints.some(endpoint => endpoint['url'].toLocaleLowerCase() === control.value.toLowerCase());
      return isDublicat ? { isDuplicate: true } : null;
    }
  }

  private validateName(control) {
    if (control && control.value) {
      const isDublicat = this.endpoints.some(endpoint => endpoint['name'].toLocaleLowerCase() === control.value.toLowerCase());
      return isDublicat ? { isDuplicate: true } : null;
    }
  }

  private providerMaxLength(control) {
    return control.value.length <= this.maxEndpointNameLength ? null : { limit: true };
  }
}

@Component({
  selector: 'endpoint-test-result-dialog',
  template: `
    <div id="dialog-box">
      <div class="dialog-header">
        <h4 class="modal-title">Endpoint test</h4>
        <button type="button" class="close" (click)="dialogRef.close()">&times;</button>
      </div>
      <div class="progress-bar" >
        <mat-progress-bar *ngIf="!response" mode="indeterminate"></mat-progress-bar>
      </div>
      <div class="content-box">
      <div mat-dialog-content class="content message">
        <p
          class="dialog-message ellipsis"
          *ngIf="!response">
          Connecting to url
          <span class="strong"
                matTooltip="{{data.url}}"
                [matTooltipPosition]="'above'"
          >
            {{cutToLongUrl(data.url)}}
          </span>
        </p>
        <p
          class="dialog-message ellipsis"
          *ngIf="isConnected && response">
          <i class="material-icons icons-possition active">check_circle</i>
          Connected to url
          <span matTooltip="{{data.url}}"
                [matTooltipPosition]="'above'"
                class="strong"
          >
            {{cutToLongUrl(data.url)}}
          </span>
        </p>
        <p class="dialog-message ellipsis"
           *ngIf="!isConnected && response"
        >
          <i class="material-icons icons-possition failed">cancel</i>
          Failed to connect to url
          <span matTooltip="{{data.url}}"
                [matTooltipPosition]="'above'"
                class="strong"
          >
            {{cutToLongUrl(data.url)}}
          </span>
        </p>
      </div>
      <div class="text-center m-top-20 m-bott-10">
        <button type="button" class="butt" mat-raised-button (click)="dialogRef.close()">Close</button>
      </div>
      </div>
    </div>
  `,
  styles: [
    `#dialog-box {overflow: hidden}
    .icons-possition {line-height: 25px; vertical-align: middle; padding-right: 7px }
    .content { color: #718ba6; padding: 15px 50px; font-size: 14px; font-weight: 400; margin: 0; }
    .info .confirm-dialog { color: #607D8B; }
    header { display: flex; justify-content: space-between; color: #607D8B; }
    header h4 i { vertical-align: bottom; }
    header a i { font-size: 20px; }
    header a:hover i { color: #35afd5; cursor: pointer; }
    label { font-size: 15px; font-weight: 500; font-family: "Open Sans",sans-serif; cursor: pointer; display: flex; align-items: center;}
    .progress-bar{ height: 4px;}
    .dialog-message{min-height: 25px; overflow: hidden;}
    `
  ]
})
export class EndpointTestResultDialogComponent {
  public isConnected = false;
  public response = false;
  constructor(
    public dialogRef: MatDialogRef<EndpointTestResultDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) {
    this.data.getStatus
      .subscribe(
        () => {
          this.isConnected = true;
          this.response = true;
          return;
        },
        () => {
          this.isConnected = false;
          this.response = true;
          return;
        });
  }
  public cutToLongUrl(url) {
    return url.length > 25 ? url.slice(0, 25) + '...' : url;
  }
}
