class SimController {
  model;
  timekeeper;

  simManager;
  taskManager;
  splash;
  overview;

  filteredDataTypes = [];

  constructor() {}

  loadSim(title) {
    return this.simManager.loadSim(title);
  }

  loadTask(title) {
    return this.taskManager.loadTask(title);
  }

  loadSplash() {
    if (this.simManager && this.simManager.sims) {
      this.simManager.sims.forEach((sim) => sim.close());
    }
    this.splash = parseSplash(this.overview.splash, this.timekeeper.running);
    $("#main").html(this.splash);
  }

  loadFirstSim() {
    // BUG: strange time delay, product is highlighted half a second before data type
    $(`#data-menu .show`).removeClass("show");
    $(`#data_type_label-0`).prop("checked", true);
    $(`#data_type-0`).addClass("show");
    $(`#product-${this.filteredDataTypes[0].products[0].name}`).prop(
      "checked",
      true
    );

    return this.loadSim(this.filteredDataTypes[0].products[0].name);
  }

  init() {
    this.model = window.model;
    this.overview = window.overview;

    /* set timekeeper instance */
    this.timekeeper = new Timekeeper(
      this.model.time.bounds.start,
      this.model.time.bounds.end,
      this.model.time.speed,
      this.model.time.revealDates
    );

    this.loadSplash();

    this.simManager = new SimManager(this.model);

    if (this.model.metadata.showHeading) {
      $("#simulator-header-title").html(this.model.metadata.name);
      $("#header").attr("style", "display: block; width: 100%;");
    }

    this.filteredDataTypes = this.model.data_types.filter( item => !item.name.includes("UTC") );
    this.displayTimeSpecificDataTypes(this.filteredDataTypes);

    this.updateDataTypesinHtml(this.filteredDataTypes);

    /* set tasks */
    this.taskManager = new TaskManager(this.model.tasks);
  }

  displayTimeSpecificDataTypes(dataTypes) {
    let timeSpecificDataTypes = this.model.data_types.filter(item => item.name.includes("UTC"));
    let timeSpecificDataTypesNames = timeSpecificDataTypes.map(item => item.name);

    const dataTypesHours = timeSpecificDataTypesNames.map(item => {
      const match = item.match(/-(\d+)UTC/);
      return match ? match[1] : null;
    });

    const subscription = this.timekeeper.clockTickObservable.subscribe((data) => {
      const currentHour = new Date(simController.getCurrentTime().toUTC().toISO()).getUTCHours();
      for (let i = 0; i < dataTypesHours.length; i++) {
        if (dataTypesHours[i] <= currentHour) {
          dataTypes.push(timeSpecificDataTypes[i]);
          this.updateDataTypesinHtml(dataTypes);
          this.loadFirstSim();
          timeSpecificDataTypes.splice(i, 1);
          dataTypesHours.splice(i, 1);
        }
      }

      // Unsubscribe
      if (dataTypesHours.length == 0) {
        subscription.unsubscribe();
      }
    }
    );
  }

  updateDataTypesinHtml(dataTypes) {
    let dataTypeList = parseDataTypes(dataTypes);
    $("#topDataMenu").html(dataTypeList);
  }

  start() {
    this.timekeeper.start();
    this.simManager.subscribe(
      this.timekeeper.clockTickObservable,
      this.timekeeper.newTimeObservable
    );
    this.taskManager.subscribe(
      this.timekeeper.clockTickObservable,
      this.timekeeper.newTimeObservable
    );
  }

  pause() {
    this.timekeeper.pause();
    this.simManager.unsubscribe();
    this.taskManager.unsubscribe();
  }

  getCurrentTime() {
    return this.timekeeper.currentTime;
  }

  getStartTime() {
    return this.timekeeper.startTime;
  }

  getEndTime() {
    return this.timekeeper.endTime;
  }

  setSimulationTime(date) {
    return this.timekeeper.setSimulationTime(date);
  }
}
