#include "Agent.h"
#include "CSVreaderModule.h"
#include "Channel.h"
#include "Sensor.h"
#include "Testbench.h"
#include "create_unit.h"
#include "mount_nodes.h"
#include "register_in_testbench.h"
#include <stdio.h>

int main(int argc, char *argv[]) {
  (void)argc, (void)argv;
  // create agents
  printf("Create Agents\n");
  Agent a_statorVoltage = create_agent("StatorVoltage");
  Agent a_statorCurrent = create_agent("StatorCurrent");
  Agent a_speed = create_agent("Speed");
  Agent a_electromagneticTorque = create_agent("ElectromagneticTorque");
  Agent a_mechanicalTorque = create_agent("MechanicalTorque");
  Agent a_viabilityMonitor = create_agent("ViabilityMonitor");

  // create sensors
  printf("\nCreate Sensors\n");
  Sensor s_statorVoltage = create_sensor("Stator Voltage");
  Sensor s_statorCurrent = create_sensor("Stator Current");
  Sensor s_speed = create_sensor("Speed");
  Sensor s_electromagneticTorque = create_sensor("Electromagnetic Torque");
  Sensor s_mechanicalTorque = create_sensor("Mechanical Torque");

  // create channels for sensors
  printf("\nCreate Channels for Sensors\n");
  Channel c_sa_statorVoltage = create_channel("Stator Voltage (SA)", 0);
  Channel c_sa_statorCurrent = create_channel("Stator Current (SA)", 0);
  Channel c_sa_speed = create_channel("Speed Sensor (SA)", 0);
  Channel c_sa_electromagneticTorque =
      create_channel("Electromagnetic Torque (SA)", 0);
  Channel c_sa_mechanicalTorque = create_channel("Mechanical Torque (SA)", 0);

  // create channels for sensors
  printf("\nCreate Channels for Agents\n");
  Channel c_aa_statorVoltage =
      create_channel("Stator Voltage (AA-UP)", MAX_BUFFER_LENGTH);
  Channel c_aa_statorCurrent =
      create_channel("Stator Current (AA-UP)", MAX_BUFFER_LENGTH);
  Channel c_aa_speed =
      create_channel("Speed Sensor (AA-UP)", MAX_BUFFER_LENGTH);
  Channel c_aa_electromagneticTorque =
      create_channel("Electromagnetic Torque (AA-UP)", MAX_BUFFER_LENGTH);
  Channel c_aa_mechanicalTorque =
      create_channel("Mechanical Torque (AA-UP)", MAX_BUFFER_LENGTH);

  // mount sensors in agents
  printf("\nMount Sensors in Agents\n");
  mount_sensorInAgent(&a_statorVoltage, &s_statorVoltage,
                      &c_sa_statorVoltage); //, &hm_s_statorVoltage);
  mount_sensorInAgent(&a_statorCurrent, &s_statorCurrent,
                      &c_sa_statorCurrent); //, &hm_s_statorCurrent);
  mount_sensorInAgent(&a_speed, &s_speed, &c_sa_speed); //, &hm_s_speed);
  mount_sensorInAgent(
      &a_electromagneticTorque, &s_electromagneticTorque,
      &c_sa_electromagneticTorque); //, &hm_s_electromagneticTorque);
  mount_sensorInAgent(&a_mechanicalTorque, &s_mechanicalTorque,
                      &c_sa_mechanicalTorque); //, &hm_s_mechanicalTorque);

  // mount agents in agent(s)
  printf("\nMount Agents in Agents\n");
  mount_agentInAgent(&a_viabilityMonitor, &a_statorVoltage,
                     &c_aa_statorVoltage);
  mount_agentInAgent(&a_viabilityMonitor, &a_statorCurrent,
                     &c_aa_statorCurrent);
  mount_agentInAgent(&a_viabilityMonitor, &a_speed, &c_aa_speed);
  mount_agentInAgent(&a_viabilityMonitor, &a_electromagneticTorque,
                     &c_aa_electromagneticTorque);
  mount_agentInAgent(&a_viabilityMonitor, &a_mechanicalTorque,
                     &c_aa_mechanicalTorque);

  // create testbench
  printf("\nCreate Testbench\n");
  Testbench tb = create_testbench("testbench");

  // csv-data
  // TODO: (1) simplify constructor, (2) check CSV for number of rows and
  // columns, (3) redesign create_CSVreaderModule function
  printf("\nCreate CSV Reader Modules\n");
  CSVreaderModule csvr_statorVoltage = create_CSVreaderModule(
      "Stator Voltage CSV-Reader",
      "C:\\csv-data\\sambamotor\\Normal_operation-Tm0\\statorVoltage.csv", 2,
      2);
  CSVreaderModule csvr_statorCurrent = create_CSVreaderModule(
      "Stator Current CSV-Reader",
      "C:\\csv-data\\sambamotor\\Normal_operation-Tm0\\statorCurrent.csv", 2,
      2);
  CSVreaderModule csvr_speed = create_CSVreaderModule(
      "Speed CSV-Reader",
      "C:\\csv-data\\sambamotor\\Normal_operation-Tm0\\speed.csv", 2, 2);
  CSVreaderModule csvr_electromagneticTorque =
      create_CSVreaderModule("Electromagnetic Torque CSV-Reader",
                             "C:\\csv-data\\sambamotor\\Normal_operation-"
                             "Tm0\\electromagneticTorque.csv",
                             2, 2);
  CSVreaderModule csvr_mechanicalTorque = create_CSVreaderModule(
      "Mechanical Torque CSV-Reader",
      "C:\\csv-data\\sambamotor\\Normal_operation-Tm0\\mechanicalTorque.csv", 2,
      2);

  // register agents
  printf("\nRegister Agents in Testbench\n");
  // TODO: "Test Bench" not "Testbench"
  register_agentInTestbench(&tb, &a_statorVoltage);
  register_agentInTestbench(&tb, &a_statorCurrent);
  register_agentInTestbench(&tb, &a_speed);
  register_agentInTestbench(&tb, &a_electromagneticTorque);
  register_agentInTestbench(&tb, &a_mechanicalTorque);
  register_agentInTestbench(&tb, &a_viabilityMonitor);

  // register sensors with their csv-readers
  printf("\nRegister Sensors in Testbench\n");
  register_sensorInTestbench(&tb, &s_statorVoltage, &csvr_statorVoltage);
  register_sensorInTestbench(&tb, &s_statorCurrent, &csvr_statorCurrent);
  register_sensorInTestbench(&tb, &s_speed, &csvr_speed);
  register_sensorInTestbench(&tb, &s_electromagneticTorque,
                             &csvr_electromagneticTorque);
  register_sensorInTestbench(&tb, &s_mechanicalTorque, &csvr_mechanicalTorque);

  // register sensor channels
  printf("\nRegister Channels in Testbench\n");
  register_channelInTestbench(&tb, &c_sa_statorVoltage);
  register_channelInTestbench(&tb, &c_sa_statorCurrent);
  register_channelInTestbench(&tb, &c_sa_speed);
  register_channelInTestbench(&tb, &c_sa_electromagneticTorque);
  register_channelInTestbench(&tb, &c_sa_mechanicalTorque);
  register_channelInTestbench(&tb, &c_aa_statorVoltage);
  register_channelInTestbench(&tb, &c_aa_statorCurrent);
  register_channelInTestbench(&tb, &c_aa_speed);
  register_channelInTestbench(&tb, &c_aa_electromagneticTorque);
  register_channelInTestbench(&tb, &c_aa_mechanicalTorque);

  printf("\n\nPress any key to start simulation...\n");
  getchar();

  // Start
  // TODO: read lenght of CSV-Files and pass this number to tb.simulate
  tb.simulate(29208);
  getchar();
}
