import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { IInstanceModel } from '@fleio-api/openstack/model/instance.model';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { InstancesApiService } from '@fleio-api/openstack/instance/instances-api.service';
import { PortsApiService } from '@fleio-api/openstack/port/ports-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { INetworkModel } from '@fleio-api/openstack/model/network.model';
import { ISubnetModel } from '@fleio-api/openstack/model/subnet.model';
import { IAction } from '@objects-view/interfaces/actions/action';
import { DialogCallbackAction } from '@objects-view/actions/dialog-callback-action';
import { IBaseDialog } from '@shared/common-dialogs/base-dialog';

@Component({
  selector: 'app-instance-details-add-port-dialog',
  templateUrl: './instance-details-add-port-dialog.component.html',
  styleUrls: ['./instance-details-add-port-dialog.component.scss']
})
export class InstanceDetailsAddPortDialogComponent implements IBaseDialog, OnInit {
  @ViewChild('formErrors') formErrors;
  networks: Array<INetworkModel>;
  subnets: Array<ISubnetModel>;
  loading = false;
  addPortForm: UntypedFormGroup = this.formBuilder.group({
    fixed_ips: this.formBuilder.array(
      []
    ),
    project: ['', Validators.required],
    network: ['', Validators.required],
    subnet: ['', Validators.required],
    device_id: [this.getInstanceId(), Validators.required],
    device_owner: ['compute:nova', Validators.required],
    region: [this.getInstanceRegion(), Validators.required],
    attach_to: ['instance', Validators.required]
  });
  dialogTitle = $localize`Add port to instance ${this.data?.instance?.name || this.data?.instance?.id}`;
  dialogActions: Array<IAction> = [
    new DialogCallbackAction({
      name: $localize`Add port`,
      primary: true,
      callback: () => this.addPort(),
    }),
  ];
  dialogForm = this.addPortForm;
  removeIpTooltip = $localize`Remove ip`;
  addIpTooltip = $localize`Add IP manually`;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private notificationService: NotificationService,
    public dialogRef: MatDialogRef<InstanceDetailsAddPortDialogComponent>,
    private instancesApi: InstancesApiService,
    private portsApi: PortsApiService,
    @Inject(MAT_DIALOG_DATA) public data: {
      instance: IInstanceModel;
      networks: Array<INetworkModel>;
    },
  ) {
  }

  getInstanceRegion() {
    if (this.data && this.data.instance) {
      return this.data.instance.region;
    }
    return '';
  }

  private getInstanceId() {
    if (this.data && this.data.instance) {
      return this.data.instance.id;
    } else {
      return '';
    }
  }

  public createPortIp() {
    return this.formBuilder.group({
      ip_address: ['', Validators.required],
    });
  }

  public addPortIp() {
    const portIps = this.addPortForm.get('fixed_ips') as UntypedFormArray;
    portIps.push(this.createPortIp());
  }

  public removeIp(index) {
    const portIps = this.addPortForm.get('fixed_ips') as UntypedFormArray;
    portIps.removeAt(index);
  }

  public changeSubnets() {
    for (const network of this.networks) {
      if (network.id === this.addPortForm.controls.network.value) {
        this.subnets = network.subnets;
        this.addPortForm.controls.subnet.setValue(this.subnets[0].id);
      }
    }
  }

  public addPort() {
    this.loading = true;
    if (!this.addPortForm.valid) {
      this.loading = false;
      return;
    }
    const value = this.addPortForm.value;
    if (value.fixed_ips.length === 0 && value.subnet) {
      value.fixed_ips = [{subnet_id: value.subnet}];
    }
    this.portsApi.create(
      value
    ).pipe().subscribe(() => {
      this.loading = false;
      this.dialogRef.close(true);
    }, error => {
      this.loading = false;
      this.formErrors.setBackendErrors(error.error.detail);
    });
  }

  ngOnInit() {
    if (this.data && this.data.instance) {
      this.networks = this.data.networks;
      if (this.networks && this.networks.length) {
        this.addPortForm.controls.network.setValue(this.networks[0].id);
      }
      this.addPortForm.controls.project.setValue(this.data.instance.project);
      this.changeSubnets();
      this.addPortForm.controls.network.valueChanges.subscribe(() => {
        this.changeSubnets();
      });
    }
  }

}
