import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Boilerplate, InferenceResults } from 'src/app/models/boilerplate.model';
import { Sections } from 'src/app/models/boilerplate.model';
import { BoilerplateService } from 'src/app/services/boilerplate.service';
import { MainService } from 'src/app/services/main.service';
import { MainDetailsComponent } from 'src/app/components/main-details/main-details.component'
import { PrefixDetailsComponent } from 'src/app/components/prefix-details/prefix-details.component'
import { SuffixDetailsComponent } from 'src/app/components/suffix-details/suffix-details.component'
import { NotifierService } from "angular-notifier";
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { CourseDialogComponentComponent, DialogData } from 'src/app/components/course-dialog-component/course-dialog-component.component';

@Component({
  selector: 'app-boilerplate-details',
  templateUrl: './boilerplate-details.component.html',
  styleUrls: ['./boilerplate-details.component.scss']

})
export class BoilerplateDetailsComponent implements OnInit {
  panelOpenState = false;

  subjects: string[] = [];

  systems?: Sections[];
  infer: InferenceResults[] = [{}];
  currentInfer?: InferenceResults = {
    infer_group_of_boilerplate: "",
    inference_data: "",
  }

  currentboilerplate: Boilerplate = {
    group_of_boilerplate: this.route.snapshot.params.gb,
    title: "",
    has_prefix: false,
    has_main: false,
    has_suffix: false
  };


  message = '';
  searchText = '';
  searchOntology = '';
  searchTextinstances = '';
  addinstance = '';
  mes_list = [] as any;
  searchInstance_list = [] as any;
  private readonly notifier: NotifierService;



  constructor(
    private mainService: MainService,
    private boilerplateService: BoilerplateService,
    private route: ActivatedRoute,
    notifierService: NotifierService,
    private router: Router,
    public dialog: MatDialog) { this.notifier = notifierService; }

  @ViewChild(MainDetailsComponent) mainchild!: MainDetailsComponent;
  @ViewChild(PrefixDetailsComponent) prefchild!: PrefixDetailsComponent;
  @ViewChild(SuffixDetailsComponent) sufchild!: SuffixDetailsComponent;

  ngOnInit(): void {
    this.message = '';
    this.getchoices(this.route.snapshot.params.gb);
    this.getBoilerplate(this.route.snapshot.params.gb, this.route.snapshot.params.id);
    this.getInfer();
  }

  searchInstance(): void {
    this.boilerplateService.searchinstances(this.route.snapshot.params.gb, this.searchTextinstances).subscribe(
      data => {
        console.log(data);
      },
      error => {
      if(error.error.detail){ this.notifier.notify("warning", (JSON.stringify(error.error.detail))); }
      if(error.error.text != 'There is no Class in the Ontology'){
        this.searchInstance_list = [error.error.text]
        //console.log(error.error.text);
      } 
      });
  }


  getInfer(): void {
    this.boilerplateService.getAllInfer(this.route.snapshot.params.gb)
      .subscribe(
        data => {
          this.currentInfer = data[0];
          this.infer = data;
        },
        error => {
          console.log(error);
        });

  }


  getBoilerplate(gb: any, id: number): void {
    this.boilerplateService.get(gb, id)
      .subscribe(
        data => {
          this.currentboilerplate = data;
          //console.log(data);
        },
        error => {
          console.log(error);
        });
  }

  updateBoilerplate(): any {
    if (this.currentboilerplate.title != "") {
      this.currentboilerplate.title = this.currentboilerplate.title?.replace(/[^\w\s]/gi, ' ')
      this.currentboilerplate.title = this.currentboilerplate.title?.replace(/ /g, "_")
    }

    this.boilerplateService.update(this.route.snapshot.params.gb, this.currentboilerplate.id, this.currentboilerplate)
      .subscribe(
        response => {
          //this.notifier.notify("success",(JSON.stringify("Requirement " + this.currentboilerplate.title + " updated")));
          //this.router.navigate(['/groupboilerplates/'+this.route.snapshot.params.gb+'/boilerplates']);
          if (this.currentboilerplate.has_prefix) { this.prefchild.getAllPrefix(this.currentboilerplate.id) };
          if (this.currentboilerplate.has_suffix) { this.sufchild.getAllSuffix(this.currentboilerplate.id); };
        },
        error => {
          this.notifier.notify("warning", (JSON.stringify(error)));
        });
  }

  updateDetailsOfBoilerplate(): any {
    if (this.currentboilerplate.has_prefix) { this.prefchild.updatePrefix() };
    if (this.currentboilerplate.has_main) { this.mainchild.updateMain(); };
    if (this.currentboilerplate.has_suffix) { this.sufchild.updateSuffix(); };
    this.notifier.notify("success", (JSON.stringify("Requirement " + this.currentboilerplate.title + " updated")));
  }

  deleteBoilerplate(): void {
    if (confirm("Αre you sure you want to delete this Boilerplate?")) {
      this.boilerplateService.delete(this.route.snapshot.params.gb, this.currentboilerplate.id)
        .subscribe(
          response => {
            //console.log(response);
            this.router.navigate(['/groupboilerplates/' + this.route.snapshot.params.gb + '/boilerplates']);
          },
          error => {
            console.log(error);
          });
    }
  }

  getchoices(gb: any): void {
    //System
    this.mainService.getdictionary(gb)
      .subscribe(
        data => {
          //console.log(data[0].Dictionary_Data);
          this.systems = data[0].Dictionary_Data

        },
        error => {
          console.log(error);
        });
  }
  details_metrics = ["isMissingConcept", "isMissingInstanceOf", "isMissingProducer", "isMissingState", "hasAmbiguousConcept", "hasAmbiguousConcept2",
    "hasNoisyConcept", "hasOpaqueConcept", "isInconsistentTo"]
  getinferdata(): any {

    if (this.currentInfer && this.currentboilerplate.title && this.mes_list.length == 0) {
      const obj = JSON.parse(this.currentInfer['inference_data'].replace(/'/g, "\""))
      this.mes_list = []
      for (let i of this.details_metrics) {
        let title = ""
        let description = ""
        let information = ""
        if (obj[i][0][this.currentboilerplate.title]?.length > 0) {
          title = '<b>Description :  </b>' + obj[i][0]['Comment']
          description = 'Invalid instances: ' + '<b>' + obj[i][0][this.currentboilerplate.title] + '</b>'
          for (let instances of obj[i][0][this.currentboilerplate.title]) {
            information += 'Above there are presented the DSO properties for the instance :  <b>' + instances + '</b>'
            for (let info of obj[i][0][instances]) { information += '<ul><li>' + info + '</ul></li>' }
          }
        }
        if (title != '' && description != "" && information != "") {
          this.mes_list.push({ 'Title': title, 'Description': description, 'Info': information })
        }
      }
    }
  }

  get_metrics(i: any): any {
    if (this.currentInfer?.inference_data) {
      const obj = JSON.parse(this.currentInfer['inference_data'].replace(/'/g, "\""))
      if (obj[i]?.length > 0) {
        this.getinferdata();
        return true
      }
    }
    return false
  }

  checklen(i: any): any {
    if (i) {
      if (i.length >= 1) { return true }
    }
    return false
  }

  deleteInstance(section: any, classes: any, subclass: any, subsubclass: any, subsubsubclass: any, subsubsubsubclass: any, instance: any, comment: any): void {
    if (confirm("Αre you sure you want to delete this Instance?")) {
      const removeinstance = section + (classes ? ' : ' + classes : '') + (subclass ? ' : ' + subclass : '') + (subsubclass ? ' : ' + subsubclass : '') + (subsubsubclass ? ' : ' + subsubsubclass : '') + (subsubsubsubclass ? ' : ' + subsubsubsubclass : '') + ' : ' + instance;
      this.mainService.deleteinstances(this.route.snapshot.params.gb, removeinstance, (comment ? comment : ' '))
        .subscribe(
          response => {
            this.prefchild.getchoices(this.route.snapshot.params.gb);
            this.mainchild.getmainchoices(this.route.snapshot.params.gb);
            this.sufchild.getflowchoices(this.route.snapshot.params.gb);
          },
          error => {
            if (error.error.text == 'Instance deleted') {
              this.notifier.notify("success", (JSON.stringify(error.error.text)));
              if (this.systems) {
                this.systems.forEach(function (value) {
                  if (section == value.Name) {
                    if (value.TheClasses) {
                      value.TheClasses.forEach(function (value) {
                        if (classes == value.Class) {
                          //UI - Add instance of a Class (e.g instance for System : Vehicle)
                          if (!subclass && !subsubclass) {
                            if (value.Instance_of_Class) {
                              let data_item = { 'Instance': instance, 'Comment': comment }
                              value.Instance_of_Class = value.Instance_of_Class.filter(item => (JSON.stringify(data_item) != JSON.stringify(item)
                              ))
                            }
                          }
                        }
                        //UI - Add instance of a SubClass (e.g instance for System : Software : Plan)
                        if (subclass && !subsubclass) {
                          if (value.Subclass) {
                            value.Subclass.forEach(function (value) {
                              if (subclass == value.SubClass_name) {
                                if (value.InstanceOfSubclass) {
                                  let data_item = { 'Instance': instance, 'Comment': comment }
                                  value.InstanceOfSubclass = value.InstanceOfSubclass.filter(item => (JSON.stringify(data_item) != JSON.stringify(item)
                                  ))
                                }
                              }
                            })
                          }
                        }
                        if (subsubclass && !subsubsubclass) {
                          if (value.Subclass) {
                            value.Subclass.forEach(function (value) {
                              if (subclass == value.SubClass_name) {
                                if (value.SubSubClass) {
                                  value.SubSubClass.forEach(function (value1) {
                                    if (value1.SubSubClass_name == subsubclass) {
                                      if (value1.SubInstanceOfSubclass) {
                                        let data_item = { 'Instance': instance, 'Comment': comment }
                                        value1.SubInstanceOfSubclass = value1.SubInstanceOfSubclass.filter(item => (JSON.stringify(data_item) != JSON.stringify(item)
                                        ))
                                      }
                                    }
                                  })
                                }
                              }
                            })
                          }
                        }
                        if (subsubsubclass && !subsubsubsubclass) {
                          if (value.Subclass) {
                            value.Subclass.forEach(function (value) {
                              if (subclass == value.SubClass_name) {
                                if (value.SubSubClass) {
                                  value.SubSubClass.forEach(function (value1) {
                                    if (value1.SubSubClass_name == subsubclass) {
                                      if (value1.SubSubClass) {
                                        value1.SubSubClass.forEach(function (value2) {
                                          if (value2.SubSubClass_name == subsubsubclass) {
                                            if (value2.SubInstanceOfSubclass) {
                                              let data_item = { 'Instance': instance, 'Comment': comment }
                                              value2.SubInstanceOfSubclass = value2.SubInstanceOfSubclass.filter(item => (JSON.stringify(data_item) != JSON.stringify(item)
                                              ))
                                            }

                                          }
                                        })
                                      }

                                    }
                                  })
                                }
                              }
                            })
                          }
                        }
                        if (subsubsubsubclass) {
                          if (value.Subclass) {
                            value.Subclass.forEach(function (value) {
                              if (subclass == value.SubClass_name) {
                                if (value.SubSubClass) {
                                  value.SubSubClass.forEach(function (value1) {
                                    if (value1.SubSubClass_name == subsubclass) {
                                      if (value1.SubSubClass) {
                                        value1.SubSubClass.forEach(function (value2) {
                                          if (value2.SubSubClass_name == subsubsubclass) {
                                            if (value2.SubSubClass) {
                                              value2.SubSubClass.forEach(function (value3) {
                                                if (value3.SubSubClass_name == subsubsubsubclass) {
                                                  if (value3.SubInstanceOfSubclass) {
                                                    let data_item = { 'Instance': instance, 'Comment': comment }
                                                    value3.SubInstanceOfSubclass = value3.SubInstanceOfSubclass.filter(item => (JSON.stringify(data_item) != JSON.stringify(item)
                                                    ))
                                                  }
                                                }
                                              })
                                            }
                                          }
                                        })
                                      }
                                    }
                                  })
                                }
                              }
                            })
                          }
                        }

                      });
                    }
                    if (!classes) {
                      let data_item = { 'Instance': instance, 'Comment': comment }
                      if (value.GeneralInstances) {
                        value.GeneralInstances = value.GeneralInstances.filter(item => (JSON.stringify(data_item) != JSON.stringify(item)))
                      }
                    }
                  }
                })
              }
              if (this.prefchild) { this.prefchild.getchoices(this.route.snapshot.params.gb); }
              if (this.mainchild) { this.mainchild.getmainchoices(this.route.snapshot.params.gb); }
              if (this.sufchild) { this.sufchild.getflowchoices(this.route.snapshot.params.gb); }
            } else { this.notifier.notify("warning", (JSON.stringify(error.error.detail))); }
          });
    }
  }

  currentDialog: DialogData = {
    instance: "",
    comment: "",
  }

  openDialog(section: any, classes: any, subclass: any, subsubclass: any, subsubsubclass: any, subsubsubsubclass: any) {
    const dialogRef = this.dialog.open(CourseDialogComponentComponent, {
      width: '500px',
      data: { name: section + (classes ? ' : ' + classes : '') + (subclass ? ' : ' + subclass : '') + (subsubclass ? ' : ' + subsubclass : '') + (subsubsubclass ? ' : ' + subsubsubclass : '') + (subsubsubsubclass ? ' : ' + subsubsubsubclass : ''), instance: this.currentDialog.instance, comment: this.currentDialog.comment },
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result.instance != "") {
        result.instance = result.instance?.replace(/[^\w\s]/gi, ' ')
        result.instance = result.instance?.replace(/ /g, "_")
      }
      if (result.instance) {
        this.addinstance = section + (classes ? ' : ' + classes : '') + (subclass ? ' : ' + subclass : '') + (subsubclass ? ' : ' + subsubclass : '') + (subsubsubclass ? ' : ' + subsubsubclass : '') + (subsubsubsubclass ? ' : ' + subsubsubsubclass : '') + ' : ' + result.instance;
        //console.log(this.addinstance);
        this.mainService.setinstances(this.route.snapshot.params.gb, this.addinstance, (result.comment ? result.comment : " "))
          .subscribe(
            data => {
              this.prefchild.getchoices(this.route.snapshot.params.gb);
              this.mainchild.getmainchoices(this.route.snapshot.params.gb);
              this.sufchild.getflowchoices(this.route.snapshot.params.gb);
              //console.log(data);
            },
            error => {
              if (error.error.text == 'Update Instance') {
                this.notifier.notify("success", (JSON.stringify(error.error.text)));
                if (this.systems) {
                  this.systems.forEach(function (value) {
                    if (section == value.Name) {
                      if (value.TheClasses) {
                        value.TheClasses.forEach(function (value) {
                          if (classes == value.Class) {
                            //UI - Add instance of a Class (e.g instance for System : Vehicle)
                            if (!subclass && !subsubclass) {
                              if (value.Instance_of_Class) {
                                value.Instance_of_Class.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                              }
                              else {
                                value.Instance_of_Class = [];
                                value.Instance_of_Class.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                              }
                            }
                            //UI - Add instance of a SubClass (e.g instance for System : Software : Plan)
                            if (subclass && !subsubclass) {
                              if (value.Subclass) {
                                value.Subclass.forEach(function (value) {
                                  if (subclass == value.SubClass_name) {
                                    //console.log('Add instance of a SubClass', value.InstanceOfSubclass);

                                    if (value.InstanceOfSubclass) {
                                      value.InstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                    }
                                    else {
                                      value.InstanceOfSubclass = [];
                                      value.InstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                    }
                                  }
                                })
                              }
                            }
                            if (subsubclass && !subsubsubclass) {
                              if (value.Subclass) {
                                value.Subclass.forEach(function (value) {
                                  if (subclass == value.SubClass_name) {
                                    if (value.SubSubClass) {
                                      value.SubSubClass.forEach(function (value1) {
                                        if (value1.SubSubClass_name == subsubclass) {
                                          if (value1.SubInstanceOfSubclass) {
                                            value1.SubInstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                          } else {
                                            value1.SubInstanceOfSubclass = [];
                                            value1.SubInstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                          }
                                        }
                                      })
                                    }
                                  }
                                })
                              }
                            }
                            if (subsubsubclass && !subsubsubsubclass) {
                              if (value.Subclass) {
                                value.Subclass.forEach(function (value) {
                                  if (subclass == value.SubClass_name) {
                                    if (value.SubSubClass) {
                                      value.SubSubClass.forEach(function (value1) {
                                        if (value1.SubSubClass_name == subsubclass) {
                                          if (value1.SubSubClass) {
                                            value1.SubSubClass.forEach(function (value2) {
                                              if (value2.SubSubClass_name == subsubsubclass) {
                                                if (value2.SubInstanceOfSubclass) {
                                                  value2.SubInstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                                } else {
                                                  value2.SubInstanceOfSubclass = [];
                                                  value2.SubInstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                                }
                                              }

                                            })
                                          }

                                        }
                                      })
                                    }
                                  }
                                })
                              }
                            }
                            if (subsubsubsubclass) {
                              if (value.Subclass) {
                                value.Subclass.forEach(function (value) {
                                  if (subclass == value.SubClass_name) {
                                    if (value.SubSubClass) {
                                      value.SubSubClass.forEach(function (value1) {
                                        if (value1.SubSubClass_name == subsubclass) {
                                          if (value1.SubSubClass) {
                                            value1.SubSubClass.forEach(function (value2) {
                                              if (value2.SubSubClass_name == subsubsubclass) {
                                                if (value2.SubSubClass) {
                                                  value2.SubSubClass.forEach(function (value3) {
                                                    if (value3.SubSubClass_name == subsubsubsubclass) {
                                                      if (value3.SubInstanceOfSubclass) {
                                                        value3.SubInstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                                      } else {
                                                        value3.SubInstanceOfSubclass = [];
                                                        value3.SubInstanceOfSubclass.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " })
                                                      }
                                                    }
                                                  })
                                                }
                                              }
                                            })
                                          }
                                        }
                                      })
                                    }
                                  }
                                })
                              }
                            }
                          }
                        });
                      }
                      if (!classes) {
                        if (value.GeneralInstances) { value.GeneralInstances.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " }) }
                        else { value.GeneralInstances = []; value.GeneralInstances.push({ "Instance": result.instance, "Comment": result.comment ? result.comment : " " }); }
                      }
                    }
                  })
                }
                if (this.prefchild) { this.prefchild.getchoices(this.route.snapshot.params.gb); }
                if (this.mainchild) { this.mainchild.getmainchoices(this.route.snapshot.params.gb); }
                if (this.sufchild) { this.sufchild.getflowchoices(this.route.snapshot.params.gb); }
              } else { this.notifier.notify("warning", (JSON.stringify(error.error.detail))); }
            });
        //this.ngOnInit();
        //Call to update instances

      }

    });
  }
  prefixs = [
    { name: 'P1', details: "If/Unless <logical expression>", explanation: 'Expresses a logical condition. Paraphrases: in case, provided that, on condition that.' },
    { name: 'P2', details: "As soon as <occuring functionality>", explanation: 'Expresses a temporal stimulation concerned with the point in time of an completed occuring functionality. Paraphrases: in the moment, immediately, once.' },
    { name: 'P3', details: "As long as <occuring functionality>", explanation: 'Expresses a temporal condition concerned with a period. The prefix clause and the main clause take place simultaneously. Paraphrases: meanwhile' },
  ];

  mains = [
    { name: 'M1', details: "system/function shall [not] set [<quantifier>] item [to stateValue]", explanation: 'Sets item Paraphrases: initiate, reset, update.' },
    { name: 'M2', details: "system/function shall [not] set state to stateValue", explanation: 'Sets state to value Paraphrases: initiate, reset, update.' },
    { name: 'M3', details: "system/function shall [not] send [<quantifier>] item", explanation: 'Sends item Paraphrases: forward.' },
    { name: 'M4', details: "system/function shall [not] receive [<quantifier>] item", explanation: 'Receives item Paraphrases: accept, acquire.' },
    { name: 'M5', details: "system/function shall [not] ingest flow", explanation: 'Ingests flow. Paraphrases: get.' },
    { name: 'M6', details: "system/function shall [not] emit flow", explanation: 'Emits flow. Paraphrases: produce.' },
    { name: 'M7', details: "system shall [not] perform function", explanation: 'System requirement. Paraphrases: execute.' },
    { name: 'M8', details: "function shall [not] invoke function", explanation: 'Function invokes another function. Paraphrases: call, request' },
    { name: 'M9', details: "system shall [not] present interface [to system]", explanation: 'Presents interface. Paraphrases: provide' },
    { name: 'M10', details: "system/interface shall [not] transfer flow/item", explanation: 'Transfers TraversingConcept. Paraphrases: transmit, broadcast' },
    { name: 'M11', details: "system shall [not] interact with system [using <connection>] [as defined in <text>]", explanation: 'System requirement expressing interface interraction' },
    { name: 'M12', details: "system shall [not] have state state [with values stateSet]", explanation: 'System requirement expressing system modes' },
    { name: 'M13', details: "system state stateValue shall [not] have substate state [with values stateSet]", explanation: 'System requirement expressing system sub modes per mode' },
    { name: 'M14', details: "system item shall [not] take values from stateSet", explanation: 'System requirement expressing item stateSet' },
    { name: 'M15', details: "system item shall [not] be composed from item", explanation: 'System requirement expressing item decomposition stateSet' },
    { name: 'M16', details: "system shall [not] contain system", explanation: 'System decomposition.' },
  ];

  suffixs = [
    { name: 'S1', details: "<numerical-afirmative> j <closed-interval> [per <time-unit>]", explanation: '' },
    { name: 'S2', details: "after/before flow", explanation: '' },
    { name: 'S3', details: "[every/for a period of/within/for at least] <number> <time-unit> [from flow]", explanation: '' },
    { name: 'S4', details: "at the beginning/at the end", explanation: '' },
    { name: 'S5', details: "at even intervals", explanation: '' },
    { name: 'S6', details: "concurently with/sequentially to <function>", explanation: '' },
  ];

  syntax = [{ pos: "Prefix", data: this.prefixs }, { pos: "Main", data: this.mains }, { pos: "Suffix", data: this.suffixs }]
}
