import { Component, OnInit } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { Observable, of } from 'rxjs';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { INetworkModel } from '@fleio-api/openstack/model/network.model';
import { NetworksApiService } from '@fleio-api/openstack/network/networks-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { INetworkCreateOptionsModel } from '@fleio-api/openstack/network/model/network-create-options.model';
import { ValidatorsHelper } from '@shared/ui-api/helpers/validators-helper';
import { MatChipEditedEvent, MatChipInputEvent } from '@angular/material/chips';
import { COMMA, ENTER } from '@angular/cdk/keycodes';

@Component({
  selector: 'app-network-edit-form',
  templateUrl: './network-edit-form.component.html',
  styleUrls: ['./network-edit-form.component.scss']
})
export class NetworkEditFormComponent extends DetailsFormBase<INetworkModel> implements OnInit {
  networkForm = this.formBuilder.group({
    name: ['', Validators.required],
    description: [''],
    region: ['', Validators.required],
    admin_state_up: [true],
    mtu: [1500, [ValidatorsHelper.requiredIntegerValidator, Validators.min(1), Validators.max(1500)]],
    dns_domain: [''],
    port_security_enabled: [true],
    tags: [[]],
  });
  createOptions: INetworkCreateOptionsModel;
  createForm = true;

  readonly separatorKeysCodes = [ENTER, COMMA] as const;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private networksApiService: NetworksApiService,
    private router: Router,
    private config: ConfigService,
    private notificationService: NotificationService,
  ) {
    super();
  }

  ngOnInit() {
    if (this.object && this.object.id) {
      this.createForm = false;
    }
    if (this.objectController) {
      this.objectController.actionCallback = () => this.networksActions();
      this.createOptions = this.objectController.additionalObjects.createOptions as INetworkCreateOptionsModel;
      if (this.createForm && this.createOptions && this.createOptions.regions && this.createOptions.regions.length) {
        this.networkForm.controls.region.patchValue(this.createOptions.regions[0].id);
      }
    }

    if (this.createOptions && this.createOptions.availability_zones &&
      this.authSvc.feature('openstack.networks.availability_zones') &&
      this.createOptions.availability_zones.length && this.createForm) {
      this.networkForm.addControl('availability_zone_hints', this.formBuilder.control([]));
    }

    if (this.createOptions.regions && this.createOptions.regions.length && !this.object.id) {
      this.networkForm.controls.region.setValue(this.createOptions.selected_region);
    }


    if (!this.createForm) {
      this.networkForm.patchValue(this.object);
      this.networkForm.controls.region.disable();
    }
  }

  tagRemoved(tagToRemove: string) {
    let tags = this.networkForm.controls.tags.value as Array<string>;
    tags = tags.filter(tag => tag !== tagToRemove);
    this.networkForm.controls.tags.setValue(tags);
  }

  tagEdited(tag: string, event: MatChipEditedEvent) {
    const value = event.value.trim();

    // Remove tag if it no longer has a value
    if (!value) {
      this.tagRemoved(tag);
      return;
    }

    // Edit existing tag
    let tags = this.networkForm.controls.tags.value as Array<string>;
    const index = tags.indexOf(tag);
    if (index >= 0) {
      tags[index] = value;
      this.networkForm.controls.tags.setValue(tags);
    }
  }

  addTag(event: MatChipInputEvent) {
    const value = (event.value || '').trim();
    if (value) {
      const tags = this.networkForm.controls.tags.value as Array<string>;
      if (tags) {
        tags.push(value);
        this.networkForm.controls.tags.setValue(tags);
      } else {
        this.networkForm.controls.tags.setValue([value]);
      }
    }

    // Clear the input value
    event.chipInput!.clear();
  }

  networksActions(): Observable<IActionResult> {
    super.ngOnInit();
    const value = this.networkForm.value;

    this.createOrUpdate(
      this.networksApiService,
      value,
    ).subscribe({
      next: () => {
        if (this.object.id) {
          this.notificationService.showMessage($localize`Network saved`);
        } else {
          this.notificationService.showMessage($localize`Network created`);
        }
        let url = this.config.getPanelUrl('openstack/networks');
        if (this.object.id) {
          url += `/${this.object.id}`;
        }
        this.router.navigateByUrl(
          url
        ).catch(() => {
        });
      }, error: () => {
        this.notificationService.showMessage($localize`Failed to save network`);
      }
    });

    return of(null);
  }
}
