import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { NotificationService } from '@shared/ui-api/notification.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { InstancesApiService } from '@fleio-api/openstack/instance/instances-api.service';
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 { ISubnetModel } from '@fleio-api/openstack/model/subnet.model';
import { INetworkModel } from '@fleio-api/openstack/model/network.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-add-ip-dialog',
  templateUrl: './instance-details-add-ip-dialog.component.html',
  styleUrls: ['./instance-details-add-ip-dialog.component.scss']
})
export class InstanceDetailsAddIpDialogComponent implements IBaseDialog, OnInit {
  @ViewChild('formErrors') formErrors;
  loading = false;
  ports: Array<IPortModel> = [];
  subnets: Array<ISubnetModel> = [];
  networks: Array<INetworkModel> = [];
  addIpForm: UntypedFormGroup = this.formBuilder.group({
    fixed_ips: this.formBuilder.array(
      [this.createIp()]
    ),
    append_ip: [true, Validators.required],
    subnet: ['', Validators.required],
    device_id: [this.getInstanceId(), Validators.required],
    device_owner: ['compute:nova', Validators.required],
    region: [this.getInstanceRegion(), 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.addIpToInstance(),
    }),
  ];
  dialogForm = this.addIpForm;
  removeIpTooltip = $localize`Remove ip`;
  addIpTooltip = $localize`Add IP`;

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

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

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

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

  public addIp() {
    const portIps = this.addIpForm.get('fixed_ips') as UntypedFormArray;
    portIps.push(this.createIp());
  }

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

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

  public addIpToInstance() {
    this.loading = true;
    if (!this.addIpForm.valid) {
      this.loading = false;
      this.addIpForm.markAllAsTouched();
      return;
    }
    const value = this.addIpForm.value;
    this.portsApi.addIp(value.port, value).subscribe({
      next: () => {
        this.loading = false;
        this.dialogRef.close(true);
      }, error: error => {
        this.loading = false;
        this.formErrors.setBackendErrors(error.error);
      }
    });
  }

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