import { Component, OnInit } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { FleioId } from '@fleio-api/base-model/base-fleio-object.model';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, 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 { IInstanceModel } from '@fleio-api/openstack/model/instance.model';
import { ClipboardService } from '@shared/ui-api/clipboard.service';
import { InstancesApiService } from '@fleio-api/openstack/instance/instances-api.service';
import { debounceTime, map, mergeMap, startWith } from 'rxjs/operators';
import { ILBMemberCreateOptionsModel } from '@fleio-api/openstack/load-balancing/model/lb-member-create-options.model';
import { LBMembersApiService } from '@fleio-api/openstack/load-balancing/members/lb-members-api.service';
import { ILBMemberModel } from '@fleio-api/openstack/load-balancing/model/lb-member.model';
import { ValidatorsHelper } from '@shared/ui-api/helpers/validators-helper';

@Component({
  selector: 'app-members-create-form',
  templateUrl: './members-create-form.component.html',
  styleUrls: ['./members-create-form.component.scss'],
  providers: [LBMembersApiService],
})
export class MembersCreateFormComponent extends DetailsFormBase<ILBMemberModel> implements OnInit {
  get loadBalancerId(): FleioId {
    return this.activatedRoute.snapshot.params.loadBalancerId;
  }

  get poolId(): FleioId {
    return this.activatedRoute.snapshot.params.id;
  }

  members = this.formBuilder.array([]);
  membersForm = this.formBuilder.group({
    members: this.members,
  });
  searchInstances = this.formBuilder.group({
    search: [''],
  });

  loading = false;
  createOptions: ILBMemberCreateOptionsModel;
  filteredInstances$: Observable<IInstanceModel[]>;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private lbMembersApiService: LBMembersApiService,
    private router: Router,
    private config: ConfigService,
    public clipboard: ClipboardService,
    private instancesApiService: InstancesApiService,
    private activatedRoute: ActivatedRoute,
  ) {
    super();
  }

  ngOnInit() {
    super.ngOnInit();
    if (this.objectController) {
      this.lbMembersApiService.setAdditionalQueryParams({pool_id: this.poolId});
      this.objectController.actionCallback = () => this.memberActions();
      if (this.objectController.additionalObjects) {
        this.createOptions = this.objectController.additionalObjects.createOptions;
      }
    }

    this.filteredInstances$ = this.searchInstances.controls.search.valueChanges.pipe(
      startWith(''),
      debounceTime(300),
      mergeMap(value => this.instancesApiService.list({
          search: value,
          openstack_project: true,
        }).pipe(map(instances => instances.objects)))
    );
  }

  addExternalPoolMember() {
    this.members.push(this.formBuilder.group({
      address: ['', Validators.required],
      protocol_port: [80, [ValidatorsHelper.requiredNumericValueValidator, Validators.min(1), Validators.max(65535)]],
      subnet_id: [''],
      weight: [1, [ValidatorsHelper.requiredNumericValueValidator, Validators.min(1)]],
    }));
  }

  removePoolMember(index: number) {
    this.members.removeAt(index);
  }

  addExistingInstance(instance: IInstanceModel) {
    const subnetId = this.createOptions.subnets.find(s => s.id === instance.access_subnet_id)?.id || '';
    this.members.push(this.formBuilder.group({
      address: [instance.access_ip, Validators.required],
      protocol_port: [80, [Validators.required, Validators.min(1), Validators.max(65535)]],
      subnet_id: [subnetId],
      weight: [1, [Validators.required, Validators.min(1)]],
    }));
  }


  memberActions(): Observable<IActionResult> {
    const value = this.membersForm.value;
    value.loadbalancer_id = this.loadBalancerId;
    this.loading = true;
    this.createOrUpdate(
      this.lbMembersApiService,
      value,
    ).subscribe(() => {
      this.router.navigate(
        [
          this.config.getPanelUrl(
            `openstack/load-balancers/${this.loadBalancerId}/pools/${this.poolId}`,
          )
        ], {
          fragment: 'members',
          queryParamsHandling: 'merge',
        }
      );
    }).add(() => {
      this.loading = false;
    });

    return of(null);
  }
}
