#include <stdbool.h>
#include <stdint.h>

#include "XMC4500.h"

#include "model_root.h"
#include "segment.h"
#include "train.h"
#include "turnout.h"

#include "model_from_solver_generator.h"

#include "close_trains.h"
#include "end_of_siding.h"
#include "misaligned_turnout.h"
#include "train_locations.h"

ModelRoot modes3_model;

CloseTrainsMatchSet close_trains_matches;
CloseTrainsFrame close_trains_frame;
MisalignedTurnoutMatchSet misaligned_turnout_matches;
MisalignedTurnoutFrame misaligned_turnout_frame;
EndOfSidingMatchSet end_of_siding_matches;
EndOfSidingFrame end_of_siding_frame;
TrainLocationsMatchSet train_locations_matches;
TrainLocationsFrame train_locations_frame;

volatile uint32_t start;
volatile uint32_t end;
volatile uint32_t time;

int main(void) {

  volatile int analysis_helper = 0;

  // Step 1: choose model

  generate_model_close_trains_solver(&modes3_model);
  // generate_model_end_of_siding_solver(&modes3_model);
  // generate_model_misaligned_turnout_solver(&modes3_model);
  // generate_model_train_locations_solver(&modes3_model);
  // generate_model_modes3(&modes3_model);

  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CYCCNT = 0;
  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

  while (1) {
    start = DWT->CYCCNT;

    // Step 2: choose query to evaluate

    close_trains_matcher(&modes3_model, &close_trains_frame, 0,
                         &close_trains_matches);
    // end_of_siding_matcher(&modes3_model, &end_of_siding_frame, 0,
    //                       &end_of_siding_matches);
    // misaligned_turnout_matcher(&modes3_model, &misaligned_turnout_frame, 0,
    //                            &misaligned_turnout_matches);
    // train_locations_matcher(&modes3_model, &train_locations_frame, 0,
    //                         &train_locations_matches);
    end = DWT->CYCCNT;
    time = end - start;

    // This flag is never set to 1, but makes the CFG connected (needed for WCET
    // analysis in OTAWA)
    if (analysis_helper == 1) {
      break;
    }
  }

  return 0;
}
