import { Component, OnInit, ViewChild } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { FormGroup, UntypedFormArray, UntypedFormBuilder, Validators } from '@angular/forms';
import { ConfigurationsApiService } from '@fleio-api/configurations/configurations-api.service';
import { ConfigService } from '@shared/config/config.service';
import { IConfigurationOpenstackModel } from '@fleio-api/configurations/model/configuration-openstack.model';
import { Observable, of } from 'rxjs';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { NotificationService } from '@shared/ui-api/notification.service';
import { MatExpansionPanel } from '@angular/material/expansion';
import { ValidatorsHelper } from '@shared/ui-api/helpers/validators-helper';

@Component({
  selector: 'app-openstack-plugin-configuration',
  templateUrl: './openstack-plugin-configuration.component.html',
  styleUrls: ['./openstack-plugin-configuration.component.scss']
})
export class OpenstackPluginConfigurationComponent extends DetailsFormBase<IConfigurationOpenstackModel> implements OnInit {
  @ViewChild('instanceTemplatesPanel') instanceTemplatesPanel: MatExpansionPanel;
  @ViewChild('imageTemplatesPanel') imageTemplatesPanel: MatExpansionPanel;
  @ViewChild('volumeTemplatesPanel') volumeTemplatesPanel: MatExpansionPanel;
  @ViewChild('floatingIpTemplatesPanel') floatingIpTemplatesPanel: MatExpansionPanel;
  @ViewChild('clusterTemplatesPanel') clusterTemplatesPanel: MatExpansionPanel;
  @ViewChild('dnsZoneTemplatesPanel') dnsZoneTemplatesPanel: MatExpansionPanel;
  @ViewChild('loadBalancerTemplatesPanel') loadBalancerTemplatesPanel: MatExpansionPanel;
  @ViewChild('dbaasInstanceTemplatesPanel') dbaasInstanceTemplatesPanel: MatExpansionPanel;

  configurationOpenstackForm = this.formBuilder.group({
    auto_cleanup_images: [false],
    auto_cleanup_number_of_days: ['', ValidatorsHelper.requiredIntegerValidator],
    auto_cleanup_image_types: ['', Validators.required],

    shelve_instances_on_suspend: [false],
    // estimation texts
    instance_price_estimate_templates: this.formBuilder.array([]),
    image_price_estimate_templates: this.formBuilder.array([]),
    volume_price_estimate_templates: this.formBuilder.array([]),
    floating_ip_price_estimate_templates: this.formBuilder.array([]),
    cluster_price_estimate_templates: this.formBuilder.array([]),
    dns_domain_price_estimate_templates: this.formBuilder.array([]),
    load_balancer_price_estimate_templates: this.formBuilder.array([]),
    dbaas_instance_price_estimate_templates: this.formBuilder.array([]),
  });
  clickToCopyTooltip = $localize`Click to copy`;

  instancePriceEstTemplates = this.configurationOpenstackForm.get('instance_price_estimate_templates') as UntypedFormArray;
  imagePriceEstTemplates = this.configurationOpenstackForm.get('image_price_estimate_templates') as UntypedFormArray;
  volumePriceEstTemplates = this.configurationOpenstackForm.get('volume_price_estimate_templates') as UntypedFormArray;
  floatingIpPriceEstTemplates = this.configurationOpenstackForm.get('floating_ip_price_estimate_templates') as UntypedFormArray;
  clusterPriceEstTemplates = this.configurationOpenstackForm.get('cluster_price_estimate_templates') as UntypedFormArray;
  dnsDomainPriceEstTemplates = this.configurationOpenstackForm.get('dns_domain_price_estimate_templates') as UntypedFormArray;
  loadBalancerPriceEstTemplates = this.configurationOpenstackForm.get('load_balancer_price_estimate_templates') as UntypedFormArray;
  dbaasInstancePriceEstTemplates = this.configurationOpenstackForm.get('dbaas_instance_price_estimate_templates') as UntypedFormArray;

  updatingControls = false;
  openstackConfiguration: IConfigurationOpenstackModel;

  constructor(
    private formBuilder: UntypedFormBuilder, private configurationsApiService: ConfigurationsApiService,
    private config: ConfigService, private notificationService: NotificationService,
  ) {
    super();
  }

  ngOnInit(): void {
    super.ngOnInit();
    if (this.objectController) {
      this.openstackConfiguration =
        this.objectController.additionalObjects.openstackConfiguration as IConfigurationOpenstackModel;
    }
    this.configurationOpenstackForm.valueChanges.subscribe(() => {
      if (!this.updatingControls) {
        this.updatingControls = true;
        this.updateControls();
        this.updatingControls = false;
      }
    });
    if (this.openstackConfiguration) {
      this.configurationOpenstackForm.patchValue(this.openstackConfiguration);
      for (const template of this.openstackConfiguration.instance_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.instancePriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.image_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.imagePriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.volume_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.volumePriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.floating_ip_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.floatingIpPriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.cluster_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.clusterPriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.dns_domain_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.dnsDomainPriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.load_balancer_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.loadBalancerPriceEstTemplates, template.language, template.content);
      }
      for (const template of this.openstackConfiguration.dbaas_instance_price_estimate_templates) {
        this.addPriceEstimateTemplate(this.dbaasInstancePriceEstTemplates, template.language, template.content);
      }
    } else {
      this.configurationOpenstackForm.disable();
    }
  }

  copyVariable(variable: string) {
    const textArea = document.createElement('textarea');
    textArea.value = variable;
    document.body.appendChild(textArea);
    textArea.select();
    document.execCommand('Copy');
    textArea.remove();
    this.notificationService.showMessage($localize`Successfully copied`);
  }

  addPriceEstimateTemplate(templates: UntypedFormArray, language = '', content = '') {
    if (templates.invalid) {
      // do not let user add new template until his previous actions are valid
      this.displayControlErrors();
      return;
    }
    const availableLanguages = this.filteredLanguages(templates, templates.length);
    if (availableLanguages.length === 0) {
      // all available languages used, cannot add new ones
      this.notificationService.showMessage($localize`All available languages were used.`);
      return;
    }
    templates.push(
      this.formBuilder.group({
        language: [language, Validators.required],
        content: [content, Validators.required],
      })
    );
  }

  removePriceEstimateTemplate(templates: UntypedFormArray, atIndex: number) {
    templates.removeAt(atIndex);
  }

  filteredLanguages(templates: UntypedFormArray, atIndex: number) {
    const usedTemplatesLanguages = [];
    for (const template of templates.controls) {
      usedTemplatesLanguages.push(template.value.language);
    }
    // return unused languages & one used language if related selector already makes use of it
    return this.openstackConfiguration.languages.filter(
      languageArr => (
          !usedTemplatesLanguages.includes(languageArr[0]) || templates.at(atIndex)?.value?.language === languageArr[0]
        )
    );
  }

  protected initTabData() {
    this.objectController.actionCallback = () => this.saveConfiguration();
  }

  updateControls() {
    const controls = this.configurationOpenstackForm.controls;
    if (controls.auto_cleanup_images.value) {
      controls.auto_cleanup_number_of_days.enable();
      controls.auto_cleanup_image_types.enable();
    } else {
      controls.auto_cleanup_number_of_days.disable();
      controls.auto_cleanup_image_types.disable();
    }
  }

  private showTemplateErrors(templatesArray: UntypedFormArray, errors: Record<number, string>, panel: MatExpansionPanel) {
    const erroredIndexes = Object.keys(errors);
    erroredIndexes.forEach(erroredIndex => {
      const formGroup = templatesArray.at(Number.parseInt(erroredIndex, 10)) as FormGroup;
      formGroup.controls.content.setErrors(errors[erroredIndex]);
    });
    panel.open();
    this.displayControlErrors();
  }

  saveConfiguration(): Observable<IActionResult> {
    const value = this.configurationOpenstackForm.value;

    this.validate();
    if (this.formGroup.invalid) {
      this.displayControlErrors();
      if (this.configurationOpenstackForm.controls.instance_price_estimate_templates.invalid) {
        this.instanceTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.image_price_estimate_templates.invalid) {
        this.imageTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.volume_price_estimate_templates.invalid) {
        this.volumeTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.floating_ip_price_estimate_templates.invalid) {
        this.floatingIpTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.cluster_price_estimate_templates.invalid) {
        this.clusterTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.dns_domain_price_estimate_templates.invalid) {
        this.dnsZoneTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.load_balancer_price_estimate_templates.invalid) {
        this.loadBalancerTemplatesPanel.open()
      }
      if (this.configurationOpenstackForm.controls.dbaas_instance_price_estimate_templates.invalid) {
        this.dbaasInstanceTemplatesPanel.open()
      }
      return of(null);
    }

    value.id = this.object.id;
    if (typeof value.auto_cleanup_image_types === 'string') {
      value.auto_cleanup_image_types = value.auto_cleanup_image_types.split(',');
    }

    const request = this.configurationsApiService.objectPutAction(value.id, 'openstack', value);

    this.objectController.loading = true;
    request.subscribe({
      next: (response) => {
        this.notificationService.showMessage(response.detail);
      },
      error: (error) => {
        if (error.error) {
          if (error.error.instance_price_estimate_templates) {
            this.showTemplateErrors(
              this.instancePriceEstTemplates,
              error.error.instance_price_estimate_templates,
              this.instanceTemplatesPanel,
            );
          } else if (error.error.image_price_estimate_templates) {
            this.showTemplateErrors(
              this.imagePriceEstTemplates,
              error.error.image_price_estimate_templates,
              this.imageTemplatesPanel,
            );
          } else if (error.error.volume_price_estimate_templates) {
            this.showTemplateErrors(
              this.volumePriceEstTemplates,
              error.error.volume_price_estimate_templates,
              this.volumeTemplatesPanel,
            );
          } else if (error.error.floating_ip_price_estimate_templates) {
            this.showTemplateErrors(
              this.floatingIpPriceEstTemplates,
              error.error.floating_ip_price_estimate_templates,
              this.floatingIpTemplatesPanel,
            );
          } else if (error.error.cluster_price_estimate_templates) {
            this.showTemplateErrors(
              this.clusterPriceEstTemplates,
              error.error.cluster_price_estimate_templates,
              this.clusterTemplatesPanel,
            );
          } else if (error.error.dns_domain_price_estimate_templates) {
            this.showTemplateErrors(
              this.dnsDomainPriceEstTemplates,
              error.error.dns_domain_price_estimate_templates,
              this.dnsZoneTemplatesPanel,
            );
          } else if (error.error.load_balancer_price_estimate_templates) {
            this.showTemplateErrors(
              this.loadBalancerPriceEstTemplates,
              error.error.load_balancer_price_estimate_templates,
              this.loadBalancerTemplatesPanel,
            );
          } else if (error.error.dbaas_instance_price_estimate_templates) {
            this.showTemplateErrors(
              this.dbaasInstancePriceEstTemplates,
              error.error.dbaas_instance_price_estimate_templates,
              this.dbaasInstanceTemplatesPanel,
            );
          } else {
            this.setErrors(error.error);
          }
        }
      }
    }).add(() => {
      this.objectController.loading = false;
    });

    return of(null);
  }

}
