import { Component, Inject, OnInit } from '@angular/core';
import {
  FormControl,
  FormGroup,
  Validators,
  FormsModule,
  FormBuilder,
} from '@angular/forms';
import {
  MatDialog,
  MatDialogRef,
  MAT_DIALOG_DATA,
} from '@angular/material/dialog';
import { CheckBoxSelectionService } from '@syncfusion/ej2-angular-dropdowns';
import { MatSnackBar } from '@angular/material/snack-bar';
import { WorkflowService } from '../../../services/samwf/workflow.service';
import { TasksInterface } from '../../../interfaces/samwf/tasks-interface';
import { TaskFields } from '@syncfusion/ej2/gantt';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { FormArray } from '@angular/forms';
import { lastValueFrom, map } from 'rxjs';
import { Logarithmic } from '@syncfusion/ej2/charts';
import { ResponseData } from 'src/app/interfaces/response-data';
import { change } from '@syncfusion/ej2/grids';
import { filter } from '@syncfusion/ej2/maps';

@Component({
  selector: 'app-workflow-pasos-form',
  templateUrl: './workflow-pasos-form.component.html',
  styleUrls: ['./workflow-pasos-form.component.css'],
  providers: [CheckBoxSelectionService],
})
export class WorkflowPasosFormComponent implements OnInit {
  formGroup: FormGroup;
  showConditionals: boolean = false;
  position = 0;
  id_workflow: any;

  workflowObject: any = {};
  workflowTasks: any[] = [];
  tasksData: any[] = [];
  action: string = '';
  data: any;
  tasks_bd: any[] = [];
  valueConditionalsArray: any[] = [];

  newSequenceCalculate: number = 0;
  nextSecuenceFlag: number = 0;
  sequenceFlag: number = 0;
  indexPositionAux = 0;

  stores = [
    { id: 0, name: 'Juan Alvarez' },
    { id: 1, name: 'Alan Carranza' },
    { id: 2, name: 'Jean Benitez' },
    { id: 4, name: 'Emmanuel Estrada' },
  ];
  arrayLettersForLevel = ['B', 'C', 'D', 'E', 'F', 'G'];

  formFields: any[] = [];
  constructor(
    private _snackBar: MatSnackBar,
    private _samwfService: WorkflowService,
    private activatedRoute: ActivatedRoute,
    private translate: TranslateService,
    private fb: FormBuilder,
    private router: Router,
    private routerNavigate: Router
  ) {
    this.id_workflow = this.activatedRoute.snapshot.paramMap.get('id');
    activatedRoute.params.subscribe((params) => {
      this.action = params['action'];
      this.data = JSON.parse(params['data']);
    });
    translate.setDefaultLang('es');
    this.tasksData = this._samwfService.getArray();

    this.formGroup = this.createFormGroup();
  }

  ngOnInit(): void {
    this.getTasksWorkflow();
  }

  createFormGroup() {
    if (this.action == 'Registrar') {
      return (this.formGroup = this.fb.group({
        id: new FormControl(''),
        tasks: new FormControl('', Validators.required),
        positionSteps: new FormControl('', Validators.required),
        positionRequired: new FormControl(this.position),
        conditionals: this.fb.array([]),
      }));
    } else {
      let positionTaskIndex = this.tasksData.findIndex((object: any) => {
        return object.id === this.data.id;
      });
      return (this.formGroup = this.fb.group({
        id: new FormControl(''),
        tasks: new FormControl(
          this.tasksData[positionTaskIndex],
          Validators.required
        ),
        positionSteps: new FormControl(''),
        positionRequired: new FormControl(this.position),
        conditionals: this.fb.array([]),
      }));
    }
  }

  deleteConditional(indice: number) {
    this.conditionals.removeAt(indice);
  }

  ////////////////////////////////// REGISTRAR ////////////////////////////
  async transformData(task: any) {
    if (this.action == 'Registrar') {
      let arrDinamic: any[] = [];
      this.calculoSecuenciaTareaPrincipal();
      let sequenceStop = 0;
      if (task.conditionals.length > 0) {
        // si tiene condicional aplicar un clicado de las condicionales presentes y llenar la nueva secuencia, nextSequence y changeSequence
        for (let index = 0; index < task.conditionals.length; index++) {
          if (index == 0) {
            task.conditionals[index].conditionalYes.sequence =
              this.getSequenceConditional(
                this.sequenceFlag,
                this.nextSecuenceFlag
              );

            task.conditionals[index].conditionalNo.sequence =
              this.getSequenceConditional(
                this.sequenceFlag,
                this.nextSecuenceFlag
              );
            sequenceStop = task.conditionals[index].conditionalNo.sequence;
            arrDinamic.push(JSON.stringify(task.conditionals[index]));
          } else {
            //pendiente de acomodar
            if (
              task.conditionals[index].indexPosition ==
              task.conditionals[index - 1].indexYes
            ) {
              task.conditionals[index].conditionalYes.sequence =
                this.getSequenceConditional(
                  task.conditionals[index - 1].conditionalYes.sequence,
                  task.conditionals[index - 1].conditionalNo.sequence
                );

              task.conditionals[index].conditionalNo.sequence =
                this.getSequenceConditional(
                  task.conditionals[index].conditionalYes.sequence,
                  task.conditionals[index - 1].conditionalNo.sequence
                );

              arrDinamic.push(JSON.stringify(task.conditionals[index]));
            } else if (
              task.conditionals[index].indexPosition ==
              task.conditionals[index - 1].indexNo
            ) {
              task.conditionals[index].conditionalYes.sequence =
                this.getSequenceConditional(
                  task.conditionals[index - 1].conditionalNo.sequence,
                  this.nextSecuenceFlag
                );

              task.conditionals[index].conditionalNo.sequence =
                this.getSequenceConditional(
                  task.conditionals[index].conditionalYes.sequence,
                  this.nextSecuenceFlag
                );
              arrDinamic.push(JSON.stringify(task.conditionals[index]));
            }
          }
        }
        this.conditionalsFormat(arrDinamic, task.tasks);
      } else {
        this.registerOneTask(task);
      }
    } else {
      this.tasksEditFormat(task);
    }
  }

  private conditionalsFormat(conditionalsJson: any, principalTask: any) {
    let arrTransform: any[] = [];
    let arrFormat: any[] = [];

    for (let index = 0; index < conditionalsJson.length; index++) {
      arrTransform.push(JSON.parse(conditionalsJson[index]));
    }
    for (let index = 0; index < arrTransform.length; index++) {
      if (index == 0) {
        if (arrTransform.length < 2) {
          arrTransform[index].conditionalYes.nextSequence =
            this.nextSecuenceFlag;

          arrFormat.push(arrTransform[index].conditionalYes);

          arrTransform[index].conditionalNo.changeSequence =
            arrTransform[index].conditionalNo.isConditional == true
              ? this.nextSecuenceFlag
              : null;

          arrFormat.push(arrTransform[index].conditionalNo);
        }
      } else {
        //pendiente de acomodar
        // Si la posicion actual del arreglo tiene el mismo nivel que la tarea anterior
        // Se añade a la anterior la referencia a la nueva tarea por medio del nextSequence y changeSequence en caso de ser el camino negativo

        if (
          arrTransform[index].indexPosition ==
            arrTransform[index - 1].indexYes &&
          arrTransform.length >= 2
        ) {
          arrTransform[index - 1].conditionalYes.nextSequence =
            arrTransform[index].conditionalYes.sequence;

          arrTransform[index - 1].conditionalYes.changeSequence =
            arrTransform[index - 1].conditionalYes.isConditional == true
              ? arrTransform[index].conditionalNo.sequence
              : null;
        } else if (
          arrTransform[index].indexPosition == arrTransform[index - 1].indexNo
        ) {
          arrTransform[index - 1].conditionalNo.nextSequence =
            arrTransform[index].conditionalYes.sequence;

          arrTransform[index - 1].conditionalNo.changeSequence =
            arrTransform[index - 1].conditionalNo.isConditional == true
              ? arrTransform[index].conditionalNo.sequence
              : null;
        }
      }
    }

    // Añadir al arreglo la informacion obtenida y separandolo por lo caminos si y no
    for (let index = 0; index < arrTransform.length; index++) {
      arrFormat.push(arrTransform[index].conditionalYes);
      arrFormat.push(arrTransform[index].conditionalNo);
    }

    arrTransform = arrTransform.filter((item, index) => {
      return arrTransform.indexOf(item) === index;
    });

    this.workflowTasks = this.workflowTasks.filter((item, index) => {
      return this.workflowTasks.indexOf(item) === index;
    });

    // Si alguna tarea no encontro coincidencias quiere decir que su camino termina en la tarea
    // Que el usuario indico como referencia en el formulario
    for (let index = 0; index < arrFormat.length; index++) {
      if (arrFormat[index].nextSequence == null) {
        arrFormat[index].nextSequence = this.nextSecuenceFlag;
      }
    }

    // Para evitar problemas de datos repetidos, a la tarea principal seleccionada
    // Se le asignan sus valores establecidos (secuencia, nextSequence y chagueSequence)
    principalTask.sequence = this.newSequenceCalculate;
    principalTask.nextSequence = arrFormat[0].sequence;
    principalTask.changeSequence = arrFormat[1].sequence;
    arrFormat.push(principalTask);

    this.registerTasks(arrFormat, principalTask.sequence);
  }

  private async registerTasks(arrCondtionals: any, principalTask: any) {
    // El arreglo workflowTasks tiene todas las tareas actuales del workflow
    // Se cicla el arreglo de tareas del formulario para asignarlas dentro del arreglo anterior

    for (let index = 0; index < arrCondtionals.length; index++) {
      this.workflowTasks.push(arrCondtionals[index]);
    }

    // Filtrar el arreglo en caso de existir tareas repetidas
    this.workflowTasks = this.workflowTasks.filter((item, index) => {
      return this.workflowTasks.indexOf(item) === index;
    });

    // Ordenar el arreglo de tareas por medio de la secuencia
    this.workflowTasks.sort((a: any, b: any) => a.sequence - b.sequence);
    console.log(this.workflowTasks);

    // Al añadir la tarea principal, la tarea anterior debe tener la nueva referencia en su nextSequence
    let positionTaskRegister = this.workflowTasks.findIndex((object: any) => {
      return object.sequence == principalTask;
    });

    this.workflowTasks[positionTaskRegister - 1].nextSequence =
      this.newSequenceCalculate;

    // Añadir las tareas al objeto del workflow en la referencia "tasks"
    this.workflowObject.tasks = this.workflowTasks;

    // Llamar al servicio para actualizar el flujo de trabajo
    this.asingTaskWorkflow();
  }

  private async registerOneTask(task: any) {
    // No aplicar filtro y solo enviarlo a registrar
    // al registrar ordenar el nuevo arreglo
    task.tasks.sequence = this.newSequenceCalculate;
    task.tasks.nextSequence = this.nextSecuenceFlag;

    // Añandir la tarea al arreglo de tareas original del workflow
    this.workflowTasks.push(task.tasks);

    // Filtrar el arreglo en caso de existir tareas repetidas
    this.workflowTasks = this.workflowTasks.filter((item, index) => {
      return this.workflowTasks.indexOf(item) === index;
    });

    // Ordenar el arreglo de tareas por medio de la secuencia
    this.workflowTasks.sort((a: any, b: any) => a.sequence - b.sequence);
    let positionTaskRegister = this.workflowTasks.findIndex((object: any) => {
      return object.sequence == task.tasks.sequence;
    });

    this.workflowTasks[positionTaskRegister - 1].nextSequence =
      this.newSequenceCalculate;
    this.workflowObject.tasks = this.workflowTasks;

    this.asingTaskWorkflow();
  }

  /////////////////////////////// MODIFICAR //////////////////////////////

  private tasksEditFormat(tasksFormatBD: any) {
    if (this.valueConditionalsArray.length == this.conditionals.value.length) {
      this.taskEditSameLength();
    } else {
      if (this.conditionals.value.length == 0) {
        this.tasksEditWithoutConditionals();
      }
    }
  }

  private tasksEditWithoutConditionals() {
    if (this.data.isConditional) {
      let filterFlow: any[] = [];
      let filterFlowAux: any[] = [];

      // Se busca la posicion del changeSequence para ir trazando el flujo de los campos

      let positionTaskChangeSequence = this.workflowTasks.findIndex(
        (object: any) => {
          return object.sequence === this.data.changeSequence;
        }
      );

      // Se crea un arreglo tomando como base la siguiente secuencia y el cambio de secuencia de la tarea principal
      // Con este arreglo se tienen las tareas del camino principal positivo
      filterFlow = this.workflowTasks.filter((object: any) => {
        return (
          object.sequence >= this.data.nextSequence &&
          object.sequence <= this.data.changeSequence
        );
      });

      // Se ciclan las tareas para obtener el ultimo cambio de secuencia y realizar un filtro como el anterior
      // Buscando obtener las tareas del camino negativo

      for (let index = 0; index < this.workflowTasks.length; index++) {
        if (
          positionTaskChangeSequence > -1 &&
          this.workflowTasks[positionTaskChangeSequence].changeSequence != null
        ) {
          if (
            this.workflowTasks[index].sequence ==
            this.workflowTasks[positionTaskChangeSequence].changeSequence
          ) {
            positionTaskChangeSequence = index;

            if (
              positionTaskChangeSequence > -1 &&
              this.workflowTasks[positionTaskChangeSequence].changeSequence !=
                null
            ) {
              if (
                this.workflowTasks[index].sequence ==
                this.workflowTasks[positionTaskChangeSequence].changeSequence
              ) {
                positionTaskChangeSequence = index;
              }
            }
          }
        }
      }

      // Con la posicion del ultimo cambio de secuencia se puede filtrar el arreglo para obtener las tareas del camino negativo
      filterFlowAux = this.workflowTasks.filter((object: any) => {
        return (
          object.sequence > this.data.changeSequence &&
          object.sequence <=
            this.workflowTasks[positionTaskChangeSequence].sequence
        );
      });

      // Union de los arreglos
      filterFlow = filterFlow.concat(filterFlowAux);
      console.log(filterFlow);

      for (let index = 0; index < filterFlow.length; index++) {
        let positionDelete = this.workflowObject.tasks.findIndex(
          (object: any) => {
            return object.sequence == filterFlow[index].sequence;
          }
        );

        this.workflowObject.tasks = this.workflowObject.tasks.filter(
          (i: any) => i != this.workflowObject.tasks[positionDelete]
        );
      }

      let taskPrincipalPosition = this.workflowObject.tasks.findIndex(
        (object: any) => {
          return object.sequence == this.data.sequence;
        }
      );

      let taskPrincipalAux = this.tasks?.value;

      taskPrincipalAux.sequence = this.data.sequence;
      taskPrincipalAux.nextSequence =
        this.workflowObject.tasks[taskPrincipalPosition + 1].sequence;
      taskPrincipalAux.changeSequence = null;

      this.workflowObject.tasks[taskPrincipalPosition] = taskPrincipalAux;
      this.asingTaskWorkflow();
    }
  }

  private async taskEditSameLength() {
    let taskToArray: any[] = [];
    let taskPrincipalPosition = this.workflowObject.tasks.findIndex(
      (object: any) => {
        return object.sequence == this.data.sequence;
      }
    );

    // Ciclar el arreglo de condicionales enviado por el usuario contra el arreglo original
    // Encontrar los datos que no cuenten con una secuencia asignada y por medio de la posicion asignarsela nuevamente
    console.log(this.valueConditionalsArray);
    console.log(this.conditionals.value);
    for (let index = 0; index < this.conditionals.value.length; index++) {
      console.log(this.conditionals.value[index].conditionalNo);
      console.log(this.conditionals.value[index].conditionalYes);

      if (
        this.conditionals.value[index].conditionalNo.sequence == null ||
        this.conditionals.value[index].conditionalNo.sequence ==
          this.conditionals.value[index].conditionalYes.sequence
      ) {
        this.conditionals.value[index].conditionalNo.sequence =
          this.valueConditionalsArray[index].conditionalNo.sequence;

        this.conditionals.value[index].conditionalNo.nextSequence =
          this.valueConditionalsArray[index].conditionalNo.nextSequence;

        this.conditionals.value[index].conditionalNo.changeSequence =
          this.valueConditionalsArray[index].conditionalNo.changeSequence;

        taskToArray.push(
          JSON.stringify(this.conditionals.value[index].conditionalNo)
        );

        taskToArray.push(
          JSON.stringify(this.conditionals.value[index].conditionalYes)
        );
      }
    }
    console.log(taskToArray);
    console.log(this.workflowObject.tasks);

    for (let index = 0; index < taskToArray.length; index++) {
      taskToArray[index] = JSON.parse(taskToArray[index]);

      let positionTask = this.workflowObject.tasks.findIndex((object: any) => {
        console.log(object.sequence + '-' + taskToArray[index].sequence);

        return object.sequence == taskToArray[index].sequence;
      });

      delete taskToArray[index].row;
      delete taskToArray[index].indexPosition;

      if (positionTask > -1) {
        this.workflowObject.tasks[positionTask] = taskToArray[index];
      }
    }
    // La tarea principal pierde los valroes por lo que se busca dentro del arreglo y se asignan de nuevo los valores
    //taskToArray.push(this.tasks?.value);

    console.log(this.workflowObject.tasks);

    //this.asingTaskWorkflow();
  }

  // Establecer el ciclo de tareas desde la base de datos
  getFlowTasks() {
    // Si la tarea recibida por el dialogo cuenta con un valor en changeSequence quiere decir que es una condicional

    if (this.data.changeSequence != null) {
      let filterFlow: any[] = [];
      let filterFlowAux: any[] = [];
      let positionTaskYes = -1;
      let positionTaskNo = -1;

      // Se busca la posicion del changeSequence para ir trazando el flujo de los campos

      let positionTaskChangeSequence = this.workflowTasks.findIndex(
        (object: any) => {
          return object.sequence === this.data.changeSequence;
        }
      );

      // Se crea un arreglo tomando como base la siguiente secuencia y el cambio de secuencia de la tarea principal
      // Con este arreglo se tienen las tareas del camino principal positivo
      filterFlow = this.workflowTasks.filter((object: any) => {
        return (
          object.sequence >= this.data.nextSequence &&
          object.sequence <= this.data.changeSequence
        );
      });

      // Se ciclan las tareas para obtener el ultimo cambio de secuencia y realizar un filtro como el anterior
      // Buscando obtener las tareas del camino negativo

      for (let index = 0; index < this.workflowTasks.length; index++) {
        if (
          positionTaskChangeSequence > -1 &&
          this.workflowTasks[positionTaskChangeSequence].changeSequence != null
        ) {
          if (
            this.workflowTasks[index].sequence ==
            this.workflowTasks[positionTaskChangeSequence].changeSequence
          ) {
            positionTaskChangeSequence = index;
            console.log(positionTaskChangeSequence);

            if (
              positionTaskChangeSequence > -1 &&
              this.workflowTasks[positionTaskChangeSequence].changeSequence !=
                null
            ) {
              if (
                this.workflowTasks[index].sequence ==
                this.workflowTasks[positionTaskChangeSequence].changeSequence
              ) {
                positionTaskChangeSequence = index;
              }
            }
          }
        }
      }

      // Con la posicion del ultimo cambio de secuencia se puede filtrar el arreglo para obtener las tareas del camino negativo
      filterFlowAux = this.workflowTasks.filter((object: any) => {
        return (
          object.sequence > this.data.changeSequence &&
          object.sequence <=
            this.workflowTasks[positionTaskChangeSequence].sequence
        );
      });

      // Union de los arreglos
      filterFlow = filterFlow.concat(filterFlowAux);

      for (let index = 0; index < filterFlow.length; index++) {
        filterFlow[index].row = index % 2 == 0 ? true : false;
      }
      // Al arreglo obtenido se realiza un filtro para obtener los niveles a los que pertenece cada tarea
      filterFlow = this.filterFlowFor(filterFlow);

      positionTaskYes = filterFlow.findIndex((object: any) => {
        return object.sequence === this.data.nextSequence;
      });

      positionTaskNo = filterFlow.findIndex((object: any) => {
        return object.sequence === this.data.changeSequence;
      });

      filterFlow[positionTaskNo].indexPosition = 'A';
      filterFlow[positionTaskNo].taskCurrent = this.data;

      filterFlow[positionTaskYes].indexPosition = 'A';
      filterFlow[positionTaskYes].taskCurrent = this.data;
      this.getFlowConditionalsAux(filterFlow);
    }
  }

  // filtrar las tareas con la secuencia asiganada originalmente
  private filterFlowFor(filterFlow: any[]) {
    let positionTaskYes = -1;
    let positionTaskNo = -1;
    let positionAuxiliarNo = -1;
    let positionAuxiliarYes = -1;
    let keyNum = 0;
    let lastIndexPosition = '1';

    for (let index = 0; index < filterFlow.length; index++) {
      positionTaskYes = filterFlow.findIndex((object: any) => {
        return object.sequence === filterFlow[index].nextSequence;
      });

      positionTaskNo = filterFlow.findIndex((object: any) => {
        return object.sequence === filterFlow[index].changeSequence;
      });

      if (positionTaskNo > -1 && positionTaskYes > -1) {
        filterFlow[positionTaskNo].taskCurrent = filterFlow[index];
        filterFlow[positionTaskYes].taskCurrent = filterFlow[index];
        console.log(filterFlow[index].row);

        if (filterFlow[index].row == true) {
          filterFlow[positionTaskNo].indexPosition =
            this.arrayLettersForLevel[keyNum] + 1;

          filterFlow[positionTaskYes].indexPosition =
            this.arrayLettersForLevel[keyNum] + 1;
          filterFlow[positionTaskYes].taskCurrent = filterFlow[index];
        } else {
          filterFlow[positionTaskNo].indexPosition =
            this.arrayLettersForLevel[keyNum] + 2;
          filterFlow[positionTaskNo].taskCurrent = filterFlow[index];

          filterFlow[positionTaskYes].indexPosition =
            this.arrayLettersForLevel[keyNum] + 2;
        }
        if (
          (filterFlow.length == 6 && index == 3) ||
          (filterFlow.length == 8 &&
            index == 6 &&
            filterFlow[index].indexPosition.includes('2'))
        ) {
          filterFlow[positionTaskNo].indexPosition =
            this.arrayLettersForLevel[keyNum] + 2;
          filterFlow[positionTaskNo].taskCurrent = filterFlow[index];

          filterFlow[positionTaskYes].indexPosition =
            this.arrayLettersForLevel[keyNum] + 2;
          filterFlow[positionTaskYes].taskCurrent = filterFlow[index];
        }

        if (filterFlow[positionTaskNo].changeSequence != null) {
          filterFlow[positionTaskNo].indexPosition =
            this.arrayLettersForLevel[keyNum] + 2;
          filterFlow[positionTaskNo].taskCurrent = filterFlow[index];

          filterFlow[positionTaskYes].indexPosition =
            this.arrayLettersForLevel[keyNum] + 2;
          filterFlow[positionTaskYes].taskCurrent = filterFlow[index];

          positionAuxiliarNo = filterFlow.findIndex((object: any) => {
            return (
              object.sequence === filterFlow[positionTaskYes].changeSequence
            );
          });

          positionAuxiliarYes = filterFlow.findIndex((object: any) => {
            return object.sequence === filterFlow[positionTaskYes].nextSequence;
          });

          if (positionAuxiliarNo > -1 && positionAuxiliarYes > -1) {
            filterFlow[positionAuxiliarNo].indexPosition =
              this.arrayLettersForLevel[keyNum] + 2;
            filterFlow[positionAuxiliarNo].taskCurrent =
              filterFlow[positionTaskNo];

            filterFlow[positionAuxiliarYes].indexPosition =
              this.arrayLettersForLevel[keyNum] + 2;
            filterFlow[positionAuxiliarYes].taskCurrent =
              filterFlow[positionTaskNo];
          }

          keyNum += 1;
        } else if (filterFlow[positionTaskYes].changeSequence != null) {
          keyNum += 1;
          positionAuxiliarNo = filterFlow.findIndex((object: any) => {
            return (
              object.sequence === filterFlow[positionTaskYes].changeSequence
            );
          });

          positionAuxiliarYes = filterFlow.findIndex((object: any) => {
            return object.sequence === filterFlow[positionTaskYes].nextSequence;
          });

          if (positionAuxiliarNo > -1 && positionAuxiliarYes > -1) {
            filterFlow[positionAuxiliarNo].indexPosition =
              this.arrayLettersForLevel[keyNum] + 1;
            filterFlow[positionAuxiliarNo].taskCurrent =
              filterFlow[positionTaskYes];

            filterFlow[positionAuxiliarYes].indexPosition =
              this.arrayLettersForLevel[keyNum] + 1;
            filterFlow[positionAuxiliarYes].taskCurrent =
              filterFlow[positionTaskYes];

            keyNum += 1;
          }
        }
      }
    }
    return filterFlow;
  }

  //establecer los campos dinamicos
  private getFlowConditionalsAux(filterFlow: any[]) {
    // Ordenar las condicionales por nivel (A, B, C)
    console.log(filterFlow);

    filterFlow = filterFlow.sort(function (indice1: any, indice2: any) {
      return indice1.indexPosition.localeCompare(indice2.indexPosition);
    });

    let arr: any[] = [];
    for (let index = 0; index < filterFlow.length; index++) {
      let positionTaskYes = -1;
      let positionTaskNo = -1;

      // Ciclar el arreglo ordenado para añadirlas al formulario dinamico

      if (filterFlow[index + 1] != undefined) {
        positionTaskYes = this.tasksData.findIndex((object: any) => {
          return object.id === filterFlow[index].id;
        });

        this.tasksData[positionTaskYes] = filterFlow[index];

        positionTaskNo = this.tasksData.findIndex((object: any) => {
          return object.id === filterFlow[index + 1].id;
        });

        this.tasksData[positionTaskNo] = filterFlow[index + 1];

        let positAux = this.tasksData.findIndex((object: any) => {
          return object.id == this.tasksData[positionTaskYes].id;
        });

        // Estructura base de el campo dinamico
        const objAux = {
          conditionalYes: this.tasksData[positionTaskYes],
          conditionalNo: this.tasksData[positionTaskNo],
          taskCurrent: this.tasksData[positAux].taskCurrent,
          indexYes: this.arrayLettersForLevel[this.indexPositionAux] + 1,
          indexNo: this.arrayLettersForLevel[this.indexPositionAux] + 2,
          indexPosition: this.tasksData[positAux].indexPosition,
        };
        arr.push(objAux);

        const conditionalsAux = this.fb.group({
          conditionalYes: new FormControl(),
          conditionalNo: new FormControl(),
          taskCurrent: new FormControl(),
          indexYes: new FormControl(),
          indexNo: new FormControl(),
          indexPosition: new FormControl(),
        });
        this.conditionals.push(conditionalsAux);
        index += 1;
        this.indexPositionAux++;
      }
    }

    // Una vez creados los campos dinamicos setearles el valor
    // !!! CON TAREAS DUPLICADAS EL SELECT QUITA EL VALOR DE LAS PRIMERAS Y DEJA LA ULTIMA
    // BUSCAR SOLUCION
    for (let index = 0; index < this.conditionals.value.length; index++) {
      this.conditionals.value[index] = arr[index];
      this.conditionals.controls[index].setValue(arr[index]);
    }

    this.valueConditionalsArray = this.conditionals.value;
  }

  // Funcion para registro  de las tareas
  private async asingTaskWorkflow() {
    await lastValueFrom(
      this._samwfService.updateWorkflow(this.workflowObject, this.id_workflow)
    ).then(
      (data: ResponseData) => {
        console.log(data);
        this._snackBar.open('!Actualización de workflow exitoso!', 'Cerrar', {
          duration: 3000,
        });

        this.conditionals.clear();
        this.routerNavigate.navigate([`/workflow/${this.id_workflow}`]);
      },
      (error) => {
        console.log(error);

        this._snackBar.open(error.message, 'Cerrar', { duration: 3000 });
      }
    );
  }

  ///////////////////////////// CALCULOS //////////////////////////////
  calculoSecuenciaTareaPrincipal() {
    // variables reutilizadas en los dos posibles casos
    let pasoAnterior: any = {};
    let secuenciaAnterior: any = 0;
    let secuenciaSiguiente = 0;
    let arrNumerosDisponibles: any[] = [];
    let pasoSiguiente: any = {};
    let secuenciaPasoRequerido: number = 0;

    if (this.action == 'Modificar') {
      this.newSequenceCalculate = this.data.sequence;
      return this.data.sequence;
    } else {
      if (this.positionRequired?.value == 1) {
        for (
          let indexFor = 0;
          indexFor < this.workflowTasks.length;
          indexFor++
        ) {
          if (
            this.workflowTasks[indexFor].sequence ==
            this.positionSteps?.value.sequence
          ) {
            if (this.workflowTasks[indexFor - 1] != null) {
              pasoAnterior = this.workflowTasks[indexFor - 1];
              secuenciaAnterior = pasoAnterior.sequence;
              secuenciaSiguiente = this.positionSteps?.value.sequence;

              for (
                let index = secuenciaAnterior;
                index <= secuenciaSiguiente;
                index++
              ) {
                if (index != secuenciaAnterior && index != secuenciaSiguiente) {
                  arrNumerosDisponibles.push(index);
                }
              }

              if (arrNumerosDisponibles.length > 0) {
                this.newSequenceCalculate = this.median(arrNumerosDisponibles);
                this.sequenceFlag = this.newSequenceCalculate;
                this.nextSecuenceFlag = secuenciaSiguiente;
              } else {
                this._snackBar.open(
                  'No puedes colocar la tarea en esta posición',
                  'Cerrar',
                  {
                    duration: 4000,
                  }
                );
                return null;
              }
              return this.newSequenceCalculate;
            } else {
              //this.dialogRef.close();
              this._snackBar.open(
                'No puedes colocar la tarea en esta posición',
                'Cerrar',
                {
                  duration: 4000,
                }
              );
              return null;
            }
          }
        }
      } else if (this.positionRequired?.value == 2) {
        // variables

        for (let index = 0; index < this.workflowTasks.length; index++) {
          if (
            this.workflowTasks[index].sequence ==
            this.positionSteps?.value.sequence
          ) {
            if (this.workflowTasks[index + 1] != null) {
              pasoSiguiente = this.workflowTasks[index + 1];
              secuenciaSiguiente = pasoSiguiente.sequence;
              secuenciaPasoRequerido = this.workflowTasks[index].sequence;

              for (
                let i = secuenciaPasoRequerido;
                i <= secuenciaSiguiente;
                i++
              ) {
                if (i != secuenciaPasoRequerido && i != secuenciaSiguiente) {
                  arrNumerosDisponibles.push(i);
                }
              }
              if (arrNumerosDisponibles.length > 0) {
                this.newSequenceCalculate = this.median(arrNumerosDisponibles);
                this.sequenceFlag = this.newSequenceCalculate;
                this.nextSecuenceFlag = secuenciaSiguiente;
              } else {
                //this.dialogRef.close();

                this._snackBar.open(
                  'No puedes colocar la tarea en esta posición',
                  'Cerrar',
                  {
                    duration: 4000,
                  }
                );
                return null;
              }
              return this.newSequenceCalculate;
            } else {
              //this.dialogRef.close();
              this._snackBar.open(
                'No puedes colocar la tarea en esta posición',
                'Cerrar',
                {
                  duration: 4000,
                }
              );
              return null;
            }
          }
        }
      }
    }
  }

  getSequenceConditional(sequenceFlag: any, nexSequence: any) {
    let arrFreeNumbers: any[] = [];

    for (let index = sequenceFlag; index <= nexSequence; index++) {
      if (index != this.newSequenceCalculate && index != nexSequence) {
        arrFreeNumbers.push(index);
      }
    }

    if (arrFreeNumbers.length > 0) {
      this.sequenceFlag = this.median(arrFreeNumbers);
      return this.sequenceFlag;
    } else {
      this._snackBar.open(
        'No quedan mas tareas, intente cambiar la posicion de la tarea',
        'Cerrar',
        {
          duration: 4000,
        }
      );
      return null;
    }
  }

  median(arr: any[]) {
    arr.sort((a, b) => a - b);
    const dimension = arr.length;
    return Math.round(
      dimension % 2 == 0
        ? arr
            .slice(dimension / 2 - 1, dimension / 2 + 1)
            .reduce((a, b) => a + b) / 2
        : arr.slice(dimension / 2, dimension / 2 + 1)[0]
    );
  }

  ///////////////// CAMPOS DINAMICOS /////////////////////////////////
  verificar(itemCondicionales: any, indice: any) {
    if (itemCondicionales.isConditional) {
      this.showConditionals = true;
      this.addConditionals(itemCondicionales, indice);
    } else {
      if (indice == 'A' && itemCondicionales.isConditional == false) {
        this.conditionals.clear();
        this.indexPositionAux = 0;
      }

      this.verifyChangesTasksForm(indice);
    }
  }

  private verifyChangesTasksForm(indice: any) {
    let arrAuxConditionals: any[] = [];
    let objAuxYes = '';
    let objAuxNo = '';

    for (let index = 0; index < this.conditionals.value.length; index++) {
      if (indice == this.conditionals.value[index].indexPosition) {
        arrAuxConditionals.push(this.conditionals.value[index].indexPosition);
        objAuxYes = this.conditionals.value[index].indexYes;
        objAuxNo = this.conditionals.value[index].indexNo;
      }

      if (arrAuxConditionals.length > 0) {
        if (objAuxNo == this.conditionals.value[index].indexPosition) {
          arrAuxConditionals.push(this.conditionals.value[index].indexPosition);
          objAuxYes = this.conditionals.value[index].indexYes;
          objAuxNo = this.conditionals.value[index].indexNo;
        } else if (objAuxYes == this.conditionals.value[index].indexPosition) {
          arrAuxConditionals.push(this.conditionals.value[index].indexPosition);
          objAuxYes = this.conditionals.value[index].indexYes;
          objAuxNo = this.conditionals.value[index].indexNo;
        }
      }
    }

    if (arrAuxConditionals.length > 0) {
      for (
        let indexConditionals = 0;
        indexConditionals < this.conditionals.value.length;
        indexConditionals++
      ) {
        for (let arrAux = 0; arrAux < arrAuxConditionals.length; arrAux++) {
          if (
            this.conditionals.value[indexConditionals].indexPosition ==
            arrAuxConditionals[arrAux]
          ) {
            this.conditionals.removeAt(indexConditionals);
          }
        }
      }

      this.showConditionals = false;
    }
  }

  verificarPosicion(itemPosicion: any) {
    this.position = itemPosicion;
  }

  addConditionals(taskCurrent: any, indice: any) {
    if (this.conditionals.value.length == 0) {
      const conditionalsAux = this.fb.group({
        conditionalYes: new FormControl(''),
        conditionalNo: new FormControl(''),
        taskCurrent: new FormControl(taskCurrent),
        indexYes: new FormControl(
          this.arrayLettersForLevel[this.indexPositionAux] + 1
        ),
        indexNo: new FormControl(
          this.arrayLettersForLevel[this.indexPositionAux] + 2
        ),
        indexPosition: new FormControl('A'),
      });
      this.conditionals.push(conditionalsAux);
      this.indexPositionAux++;
    } else {
      if (this.conditionals.value.length <= 3) {
        let position = this.conditionals.value.findIndex(
          (object: any) => object.indexPosition == indice
        );

        const conditionals = this.fb.group({
          conditionalYes: new FormControl(''),
          conditionalNo: new FormControl(''),
          taskCurrent: new FormControl(taskCurrent),
          indexPosition: new FormControl(indice),
          indexYes: new FormControl(
            this.arrayLettersForLevel[this.indexPositionAux] + '1'
          ),
          indexNo: new FormControl(
            this.arrayLettersForLevel[this.indexPositionAux] + '2'
          ),
        });

        if (position <= -1) {
          this.conditionals.push(conditionals);
          let arr = this.conditionals.value.sort(function (
            indice1: any,
            indice2: any
          ) {
            return indice1.indexPosition.localeCompare(indice2.indexPosition);
          });
          this.conditionals.setValue(arr);
          this.indexPositionAux++;
        }
      } else {
        this._snackBar.open('Alcanzo el maximo de condicionales', 'Cerrar', {
          duration: 3000,
        });
      }
    }
  }

  ////////////// CONSULTAS /////////////////////////////////////////
  private async getTasksWorkflow() {
    await lastValueFrom(this._samwfService.getWorkflow(this.id_workflow)).then(
      async (data: any) => {
        this.workflowObject = data;

        /*         this.workflowTasks = data.tasks.filter(
          (object: any) => object.isAvailable != false
        ); */
        this.workflowTasks = data.tasks;
        if (this.action == 'Modificar') {
          this.getFlowTasks();
        }
      },
      (error: any) => {
        console.error(error);

        this._snackBar.open(error.message, 'Cerrar', { duration: 3000 });
      }
    );
  }

  backToWorkflows() {
    this.routerNavigate.navigate([`workflow/${this.id_workflow}`]);
  }

  get tasks() {
    return this.formGroup.get('tasks');
  }

  get notification() {
    return this.formGroup.get('notification');
  }

  get conditionals(): FormArray {
    return this.formGroup.get('conditionals') as FormArray;
  }

  get sequence() {
    return this.formGroup.get('sequence');
  }

  get positionSteps() {
    return this.formGroup.get('positionSteps');
  }

  get positionRequired() {
    return this.formGroup.get('positionRequired');
  }

  get employees() {
    return this.formGroup.get('employees');
  }

  get employeesNotification() {
    return this.formGroup.get('employeesNotification');
  }

  get taskCurrent() {
    return this.formGroup.get('taskCurrent');
  }
}
