#include "simdata.h"

namespace germanairlinesva_simdata
{
  int scan(
      const char *defaultFile,
      const char *sceneryPack,
      const char *logFile,
      std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
          &airports)
  {
    std::ifstream base(defaultFile);
    if (!base.good()) {
      return 1;
    }
    std::ifstream custom(sceneryPack);
    if (!custom.good()) {
      base.close();
      return 2;
    }
    std::ofstream logfile(logFile, std::fstream::trunc);
    if (!logfile.good()) {
      base.close();
      custom.close();
      return 3;
    }

    // Default
    logfile << "<FILE> " << defaultFile << std::endl;
    makeAirport("DEFAULT", &base, &airports, &logfile);
    base.close();

    std::string line;
    size_t pos;
    std::vector<std::string> packs;
    while (std::getline(custom, line)) {
      if ((pos = line.find("SCENERY_PACK")) != std::string::npos) {
        std::string path =
            germanairlinesva_util::rtrim_copy(line.substr(pos + 13)) +
            "Earth nav data/apt.dat";
        packs.push_back(path);
      }
    }
    std::reverse(packs.begin(), packs.end());

    for (std::string const &path : packs) {
      std::ifstream pack(path);
      if (pack.good()) {
        logfile << "<FILE> " << path << std::endl;
        makeAirport("CUSTOM", &pack, &airports, &logfile);
        pack.close();
      } else {
        pack.close();
        logfile << "<STATUS>"
                << "Could not find " << path << std::endl;
      }
    }

    logfile << std::endl
            << "<STATUS> Total airports: " << airports.size() << std::endl;

    custom.close();
    logfile.close();
    return 0;
  }

  void makeAirport(
      const std::string &kind,
      std::ifstream *infile,
      std::map<std::string, std::pair<std::vector<Gate>, std::vector<Runway>>>
          *airports,
      std::ofstream *logfile)
  {
    std::string line;
    std::string *currentIcao = nullptr;
    std::vector<Gate> tmpGates;
    std::vector<Runway> tmpRunways;

    int apCount = 0;
    int validCount = 0;

    while (std::getline(*infile, line)) {
      std::vector<std::string> fields = germanairlinesva_util::split(line, ' ');
      fields = germanairlinesva_util::select_T<std::string>(
          fields,
          [](const std::string &s) { return s.length() > 0; });

      if (fields.empty())
        continue;
      if (fields[0] == "1") {
        // Write to file if ICAO is valid, and we have gates and runways
        if (currentIcao != nullptr && !tmpRunways.empty() &&
            !tmpGates.empty()) {
          (*airports)[*currentIcao] = {tmpGates, tmpRunways};
          validCount += 1;
          *logfile << "\t<STATUS> " << *currentIcao << " committed"
                   << std::endl;
        } else if (currentIcao != nullptr) {
          *logfile << "\t<STATUS> " << *currentIcao
                   << " had no gates or runways" << std::endl;
        }
        tmpGates = std::vector<Gate>();
        tmpRunways = std::vector<Runway>();
        currentIcao = new std::string(fields[4]);
        apCount += 1;
        *logfile << "\t<" << kind << "> " << line << std::endl;
      } else if (currentIcao != nullptr && fields[0] == "15") {
        makeGate15(&tmpGates, fields);
        *logfile << "\t\t<GATE OLD> " << line << std::endl;
      } else if (fields[0] == "16" || fields[0] == "17") {
        // Write to file if ICAO is valid, and we have gates and runways
        if (currentIcao != nullptr && !tmpRunways.empty() &&
            !tmpGates.empty()) {
          (*airports)[*currentIcao] = {tmpGates, tmpRunways};
          validCount += 1;
          *logfile << "\t<STATUS> " << *currentIcao << " committed"
                   << std::endl;
        } else if (currentIcao != nullptr) {
          *logfile << "\t<STATUS> " << *currentIcao
                   << " had no gates or runways" << std::endl;
        }
        tmpGates = std::vector<Gate>();
        tmpRunways = std::vector<Runway>();
        currentIcao = nullptr;
        *logfile << "\t<" << kind << " SKIPPED> " << line << std::endl;
      } else if (currentIcao != nullptr && fields[0] == "100") {
        makeRunway(&tmpRunways, fields);
        *logfile << "\t\t<RUNWAY> " << line << std::endl;
      } else if (currentIcao != nullptr && fields[0] == "1300") {
        makeGate1300(&tmpGates, fields);
        *logfile << "\t\t<GATE> " << line << std::endl;
      }
    }

    if (currentIcao != nullptr && !tmpRunways.empty() && !tmpGates.empty()) {
      (*airports)[*currentIcao] = {tmpGates, tmpRunways};
      validCount += 1;
      *logfile << "\t<STATUS> " << *currentIcao << " committed" << std::endl;
    }
    *logfile << "<STATUS> " << apCount << " airports found, of which "
             << validCount << " are valid" << std::endl;
  }

  void makeGate15(std::vector<Gate> *gates, std::vector<std::string> fields)
  {
    std::string gateName;
    for (size_t j = 4; j < fields.size() - 1; j++) {
      gateName += fields[j] + " ";
    }
    gateName += fields.back();
    gateName = std::regex_replace(gateName, std::regex{","}, "0");

    gates->push_back(
        Gate{gateName, std::stod(fields[1]), std::stod(fields[2]), 40});
  }

  void makeRunway(std::vector<Runway> *runways, std::vector<std::string> fields)
  {
    runways->push_back(Runway{fields[8],
                              std::stod(fields[9]),
                              std::stod(fields[10]),
                              std::stod(fields[18]),
                              std::stod(fields[19]),
                              std::stod(fields[1])});
    runways->push_back(Runway{fields[17],
                              std::stod(fields[18]),
                              std::stod(fields[19]),
                              std::stod(fields[9]),
                              std::stod(fields[10]),
                              std::stod(fields[1])});
  }

  void makeGate1300(std::vector<Gate> *gates, std::vector<std::string> fields)
  {
    std::string gateName;
    for (size_t j = 6; j < fields.size() - 1; j++) {
      gateName += fields[j] + " ";
    }
    gateName += fields.back();
    gateName = std::regex_replace(gateName, std::regex{","}, "0");

    gates->push_back(
        Gate{gateName, std::stod(fields[1]), std::stod(fields[2]), 40});
  }
} // namespace germanairlinesva_simdata