import { Component, OnInit } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { IPortModel } from '@fleio-api/openstack/model/port.model';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { IPortCreateOptionsModel } from '@fleio-api/openstack/model/port-create-options.model';
import { PortsApiService } from '@fleio-api/openstack/port/ports-api.service';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { NetworksApiService } from '@fleio-api/openstack/network/networks-api.service';
import { INetworkModel } from '@fleio-api/openstack/model/network.model';

@Component({
  selector: 'app-port-edit-form',
  templateUrl: './port-edit-form.component.html',
  styleUrls: ['./port-edit-form.component.scss']
})
export class PortEditFormComponent extends DetailsFormBase<IPortModel> implements OnInit {
  portForm = this.formBuilder.group({
    name: [''],
    admin_state_up: [true],
    network: ['', Validators.required],
    ip_address_or_subnet: [''],
    subnet: ['', Validators.required],
    fixed_ips: this.formBuilder.array([]),
    mac_address: [''],
    port_security_enabled: [true],
    vnic_type: [''],
    description: [''],
  });
  fixedIps: UntypedFormArray = this.portForm.controls.fixed_ips as UntypedFormArray;
  createOptions: IPortCreateOptionsModel;
  isEditForm: boolean;
  extraData;
  networkSelectedPlaceholder = $localize`Network`;
  networkUnselectedPlaceholder = $localize`Select network ...`;
  removeFixedIpTooltip = $localize`Remove fixed IP`;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private portsApiService: PortsApiService,
    private router: Router,
    private config: ConfigService,
    public networksApiService: NetworksApiService,
  ) {
    super();
  }

  networkDisplayFn(network: INetworkModel) {
    if (!network) {
      return '';
    }
    return `${network.name} - ${network.id} - ${network.region}`;
  }

  changeDestination(value) {
    // createInClientProject
    if (value === false) {
      this.portForm.controls.client.setValue('');
      this.portForm.controls.client.clearValidators();
      this.portForm.controls.client.reset();
    } else {
      this.portForm.controls.client.setValidators(Validators.required);
    }
  }

  addFixedIp(value = '') {
    this.fixedIps.push(
      this.formBuilder.group({
        ip_address: [value, Validators.required],
      })
    );
  }

  deleteFixedIp(index: number) {
    this.fixedIps.removeAt(index);
  }

  ngOnInit() {
    super.ngOnInit();

    if (this.objectController) {
      this.objectController.actionCallback = () => this.portActions();
      if (this.objectController.additionalObjects) {
        this.createOptions = this.objectController.additionalObjects.createOptions as IPortCreateOptionsModel;
      }
    }

    if (this.object && this.object.extra) {
      this.extraData = JSON.parse(
        this.object.extra.replace(/'/g, '"').replace(/None/g, 'null')
      );
    }

    if (this.object && this.object.id) {
      this.portForm.controls.network.disable();
      this.isEditForm = true;
      this.portForm.patchValue(this.object);
      if (this.extraData && this.extraData['binding:vnic_type']) {
        this.portForm.controls.vnic_type.setValue(this.extraData['binding:vnic_type']);
      }

      this.networksApiService.get(this.object.network).subscribe(network => {
        this.portForm.controls.network.setValue(network);
      });

      if (this.object.fixed_ips.length) {
        this.portForm.controls.ip_address_or_subnet.setValue('fixed_ip_address');
        this.portForm.controls.subnet.setValue(this.object.fixed_ips[0].subnet_id);
        for (const ipData of this.object.fixed_ips) {
          this.addFixedIp(ipData.ip_address);
        }
      }
    }

    this.portForm.controls.ip_address_or_subnet.valueChanges.subscribe(value => {
      this.ipAddressOrSubnetUpdated(value);
    });

    if (this.createOptions) {
      this.portForm.controls.vnic_type.setValue(this.createOptions.vnic_types[0][0]);
    }

    this.ipAddressOrSubnetUpdated(this.portForm.controls.ip_address_or_subnet.value);
  }

  ipAddressOrSubnetUpdated(value) {
    if (value === 'fixed_ip_address') {
      this.portForm.controls.fixed_ips.enable();
    } else {
      this.portForm.controls.fixed_ips.disable();
    }
    if (value === 'subnet') {
      this.portForm.controls.subnet.enable();
    } else {
      this.portForm.controls.subnet.disable();
    }
  }

  portActions(): Observable<IActionResult> {
    const value = this.portForm.value as any;

    if (value.ip_address_or_subnet === 'subnet') {
      value.fixed_ips = [];
      value.fixed_ips.push({
        subnet_id: value.subnet
      });
    }

    const port = {...this.object, ...value};

    this.createOrUpdate(
      this.portsApiService,
      port,
      true,
    ).subscribe({
      next: () => {
        this.router.navigateByUrl(
          this.config.getPrevUrl('openstack/ports')
        ).catch(() => {
        });
      }, error: error => {
        if (error?.error?.fixed_ips) {
          // handle fixed_ips array errors
          let i = 0;
          for (const fixedIpError of error.error.fixed_ips) {
            const formGroup = (this.fixedIps.at(i) as UntypedFormGroup);
            formGroup.controls.ip_address.setErrors(fixedIpError.ip_address);
            formGroup.markAllAsTouched();
            i += 1;
          }
        }
      }
    });

    return of(null);
  }
}
