#pragma once

inline void EngineConfig_Init(EngineConfig *config) {
  //config->storage_config    = StorageConfig("C:\\Users\\TRIZ\\clones\\osrm_test\\data\\algeria-260108.osrm");
  config->storage_config    = StorageConfig(config_global.osrm_path);
  config->use_shared_memory = false;
  config->algorithm         = EngineConfig::Algorithm::CH; // This needs osrm-extract and osrm-contract, for MLD you need osrm-extract osrm-partition osrm-customize.
}

inline void MatchParameters_Init(MatchParameters *params) {
  params->steps       = false;
  params->annotations = false;
  params->tidy        = true;
  params->overview    = RouteParameters::OverviewType::Full;
}

inline void MatchParameters_Add(MatchParameters *params, Location l) {
  double radius = std::max(l.accuracy * 1.2, 8.0);
  params->coordinates.push_back({util::FloatLongitude{l.longitude}, util::FloatLatitude{l.latitude}});
  params->timestamps .push_back(l.time);
  params->radiuses   .push_back(radius);
}

inline void RouteParameters_Init(RouteParameters *params) {
  params->overview = RouteParameters::OverviewType::Full;
  //params.alternatives = 2;
}


void Geometry_Add(std::vector<std::string>& geometries, double *distance, json::Object json_object, std::string key) {
  assert(key == "routes" || key == "matchings");

  if (json_object.values.find(key) == json_object.values.end()) return;

  auto& routes = std::get<osrm::json::Array>(json_object.values[key]);
  if (routes.values.empty()) return;

  for (size_t i = 0; i < routes.values.size(); ++i) {
    auto& route = std::get<osrm::json::Object>(routes.values[i]);
    if (route.values.find("geometry") == route.values.end()) return;
    // Correct way to get distance  
    auto distance_it = route.values.find("distance");  
    if (distance_it != route.values.end()) {  
      *distance += std::get<osrm::json::Number>(distance_it->second).value;  
      //fprintf(stderr, "Distance %f\n", *distance);  
    } 
    auto& geometry = std::get<osrm::util::json::String>(route.values["geometry"]);
    geometries.push_back(geometry.value);
  }
}

void RouteParameters_RouteGaps(OSRM *osrm, RouteParameters *params, std::vector<std::string> &geometries_from_routes, double *distance_traveled, util::Coordinate start, util::Coordinate end) {
  params->coordinates.clear();
  params->coordinates.push_back(start);
  params->coordinates.push_back(end);

  json::Object result;
  auto status = osrm->Route(*params, result);

  if (status != Status::Ok) {
    std::string output;
    json::render(output, result);
    fprintf(stderr, "Route has Failed!\noutput: %s\n", output.c_str());
    return;
  }
  Geometry_Add(geometries_from_routes, distance_traveled, result, "routes");
}
