#include "godot_scene.h"
#include <fstream>
#include <sstream>
#include <string_view>
#include <variant>
namespace com::fourisland::lingo2_archipelago {
namespace {
struct Heading {
std::string type;
std::string id;
std::string path;
std::string resource_type;
std::string name;
std::string parent;
GodotInstanceType instance_type;
};
Heading ParseTscnHeading(std::string_view line) {
std::string original_line(line);
Heading heading;
if (line[0] != '[') {
std::ostringstream errormsg;
errormsg << "Heading must start with [." << std::endl
<< "Bad heading: " << original_line;
throw std::invalid_argument(errormsg.str());
}
line.remove_prefix(1);
int divider = line.find_first_of(" ]");
if (divider == std::string_view::npos) {
std::ostringstream errormsg;
errormsg << "Malformatted heading: " << line << std::endl
<< "Original line: " << original_line;
throw std::invalid_argument(errormsg.str());
}
heading.type = std::string(line.substr(0, divider));
line.remove_prefix(divider + 1);
while (!line.empty()) {
divider = line.find_first_of("=");
if (divider == std::string_view::npos) {
std::ostringstream errormsg;
errormsg << "Malformatted heading: " << line << std::endl
<< "Original line: " << original_line;
throw std::invalid_argument(errormsg.str());
}
std::string key(line.substr(0, divider));
line.remove_prefix(divider + 1);
if (line[0] == '"') {
line.remove_prefix(1);
divider = line.find_first_of("\"");
if (divider == std::string_view::npos) {
std::ostringstream errormsg;
errormsg << "Malformatted heading: " << line << std::endl
<< "Original line: " << original_line;
throw std::invalid_argument(errormsg.str());
}
std::string strval(line.substr(0, divider));
line.remove_prefix(divider + 2);
if (key == "name") {
heading.name = strval;
} else if (key == "parent") {
heading.parent = strval;
} else if (key == "path") {
heading.path = strval;
} else if (key == "type") {
heading.resource_type = strval;
} else if (key == "id") {
heading.id = strval;
}
} else if (line[0] == 'S' || line[0] == 'E') {
GodotInstanceType rrval;
char internal = line[0];
line.remove_prefix(13); // SubResource("
divider = line.find_first_of("\"");
if (divider == std::string_view::npos) {
std::ostringstream errormsg;
errormsg << "Malformatted heading: " << line << std::endl
<< "Original line: " << original_line;
throw std::invalid_argument(errormsg.str());
}
std::string refid = std::string(line.substr(0, divider));
line.remove_prefix(divider + 3);
GodotInstanceType instance_type;
if (internal == 'E') {
instance_type = GodotExtResourceRef{.id = refid};
} else {
// SubResource is not supported right now.
}
if (key == "instance") {
heading.instance_type = instance_type;
} else {
// Other keys aren't supported right now.
}
} else {
divider = line.find_first_of(" ]");
if (divider == std::string_view::npos) {
std::ostringstream errormsg;
errormsg << "Malformatted heading: " << line << std::endl
<< "Original line: " << original_line;
throw std::invalid_argument(errormsg.str());
}
int numval = std::atoi(line.substr(0, divider).data());
line.remove_prefix(divider + 1);
// keyvals_[key] = numval;
}
}
return heading;
}
} // namespace
std::string GodotNode::GetPath() const {
if (parent.empty() || parent == ".") {
return name;
} else {
return parent + "/" + name;
}
}
GodotScene ReadGodotSceneFromFile(const std::string& path) {
std::map<std::string, GodotExtResource> ext_resources;
std::vector<GodotNode> nodes;
std::ifstream input(path);
std::string line;
bool section_started = false;
Heading cur_heading;
std::ostringstream cur_value;
bool value_started = false;
auto handle_end_of_section = [&]() {
section_started = false;
value_started = false;
if (cur_heading.type == "sub_resource") {
// sub_resources_[std::get<int>(cur_heading.GetKeyval("id"))] =
// {cur_heading, cur_value.str(), ""};
} else {
// other_.emplace_back(cur_heading, cur_value.str());
}
cur_value = {};
};
while (std::getline(input, line)) {
if (section_started && (line.empty() || line[0] == '[')) {
handle_end_of_section();
}
if (!line.empty() && line[0] == '[') {
Heading heading = ParseTscnHeading(line);
if (heading.type == "gd_scene") {
// file_descriptor_ = heading;
} else if (heading.type == "ext_resource") {
GodotExtResource ext_resource;
ext_resource.path = heading.path;
ext_resource.type = heading.resource_type;
ext_resources[heading.id] = ext_resource;
} else if (heading.type == "node") {
if (heading.parent != "") {
nodes.push_back(GodotNode{.name = heading.name,
.parent = heading.parent,
.instance_type = heading.instance_type});
}
} else {
cur_heading = heading;
section_started = true;
}
} else if (!line.empty()) {
if (value_started) {
cur_value << std::endl;
} else {
value_started = true;
}
cur_value << line;
}
}
if (section_started) {
handle_end_of_section();
}
return GodotScene(std::move(ext_resources), std::move(nodes));
}
} // namespace com::fourisland::lingo2_archipelago