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

@Component({
  selector: 'app-instance-details-auto-add-ip-dialog',
  templateUrl: './instance-details-auto-add-ip-dialog.component.html',
  styleUrls: ['./instance-details-auto-add-ip-dialog.component.scss']
})
export class InstanceDetailsAutoAddIpDialogComponent implements IBaseDialog, OnInit {
  @ViewChild('formErrors') formErrors;
  ipsToAllocate = 1;
  loading = false;
  networks: Array<INetworkModel> = [];
  ports: Array<IPortModel> = [];
  subnets: Array<ISubnetModel> = [];
  addIpAutomaticallyForm: UntypedFormGroup = this.formBuilder.group({
    fixed_ips: this.formBuilder.array(
      []
    ),
    append_ip: [true, Validators.required],
    subnet: ['', Validators.required],
    device_id: [this.getDeviceId(), Validators.required],
    device_owner: ['compute:nova', Validators.required],
    region: [this.getRegion(), Validators.required],
    port: ['', Validators.required],
  });
  dialogTitle = $localize`Add IP to instance ${this.data?.instance?.name || this.data?.instance?.id}`;
  dialogActions: Array<IAction> = [
    new DialogCallbackAction({
      name: $localize`Add ip`,
      primary: true,
      callback: () => this.addIpsAutomatically(),
    }),
  ];
  dialogForm = this.addIpAutomaticallyForm;

  getDeviceId() {
    if (this.data && this.data.instance) {
      return this.data.instance.id;
    }
    return '';
  }

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

  constructor(
    private formBuilder: UntypedFormBuilder,
    public dialogRef: MatDialogRef<InstanceDetailsAutoAddIpDialogComponent>,
    private portsApi: PortsApiService,
    @Inject(MAT_DIALOG_DATA) public data: {
      instance: IInstanceModel;
      ports: Array<IPortModel>;
      networks: Array<INetworkModel>;
    }
  ) {
  }

  private createIp(subnetId) {
    return this.formBuilder.group({
      subnet_id: [subnetId, Validators.required],
    });
  }

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

  public addIpsAutomatically() {
    this.loading = true;
    if (!this.addIpAutomaticallyForm.valid) {
      this.loading = false;
      return;
    }
    const value = this.addIpAutomaticallyForm.value;
    const fixedIps = this.addIpAutomaticallyForm.get('fixed_ips') as UntypedFormArray;
    for (let i = 0; i < this.ipsToAllocate; i++) {
      fixedIps.push(this.createIp(this.addIpAutomaticallyForm.controls.subnet.value));
    }
    if (value) {
      this.portsApi.automaticAddIps(
        value.port, this.data.instance.region, this.addIpAutomaticallyForm.get('fixed_ips').value,
      ).subscribe({
        next: () => {
          this.loading = false;
          this.dialogRef.close(true);
        }, error: error => {
          this.loading = false;
          const fixedIpsSubmitted = this.addIpAutomaticallyForm.get('fixed_ips') as UntypedFormArray;
          for (let i = 0; i < fixedIpsSubmitted.length; i++) {
            // clear submitted ips
            fixedIpsSubmitted.removeAt(i);
          }
          this.formErrors.setBackendErrors(error.error.detail);
        }
      });
    }
  }

  ngOnInit() {
    if (this.data) {
      this.ports = this.data.ports;
      this.networks = this.data.networks;
      this.addIpAutomaticallyForm.controls.port.valueChanges.subscribe(() => {
        this.changeSubnets();
      });
      if (this.ports && this.ports.length) {
        this.addIpAutomaticallyForm.controls.port.setValue(this.ports[0].id);
      }
    }
  }

}
