#include "io/PlanXmlReader.h"
#include <wx/xml/xml.h>
#include <wx/string.h>

namespace MC {

static std::string A(wxXmlNode* n, const wxString& attr) {
    return n->GetAttribute(attr, "").ToStdString();
}
static int AI(wxXmlNode* n, const wxString& attr) {
    long v = 0;
    n->GetAttribute(attr, "0").ToLong(&v);
    return (int)v;
}

bool PlanXmlReader::Read(const std::string& filePath, RocrailPlan& plan) {
    wxXmlDocument doc;
    if (!doc.Load(wxString::FromUTF8(filePath))) {
        m_lastError = "Failed to load: " + filePath;
        return false;
    }

    wxXmlNode* root = doc.GetRoot();
    if (!root || root->GetName() != "plan") {
        m_lastError = "Missing <plan> root";
        return false;
    }

    plan.title = A(root, "title");

    for (wxXmlNode* n = root->GetChildren(); n; n = n->GetNext()) {
        const wxString& tag = n->GetName();

        if (tag == "tk") {
            PlanTrack tk;
            tk.id   = A(n, "id");
            tk.x    = AI(n, "x");
            tk.y    = AI(n, "y");
            tk.type = A(n, "type");
            tk.ori  = A(n, "ori");
            plan.tracks.push_back(tk);
        }
        else if (tag == "bk") {
            PlanBlock bk;
            bk.id  = A(n, "id");
            bk.x   = AI(n, "x");
            bk.y   = AI(n, "y");
            bk.ori = A(n, "ori");
            bk.visW = (bk.ori == "east" || bk.ori == "west") ? 4 : 1;
            bk.visH = (bk.ori == "east" || bk.ori == "west") ? 1 : 4;
            plan.blocks.push_back(bk);
        }
        else if (tag == "fb") {
            PlanSensor fb;
            fb.id      = A(n, "id");
            fb.addr    = AI(n, "addr");
            fb.x       = AI(n, "x");
            fb.y       = AI(n, "y");
            fb.ori     = A(n, "ori");
            fb.blockId = A(n, "blockId");
            fb.role    = A(n, "role");
            plan.sensors.push_back(fb);
        }
        else if (tag == "sw") {
            PlanSwitch sw;
            sw.id       = A(n, "id");
            sw.type     = A(n, "type");
            sw.x        = AI(n, "x");
            sw.y        = AI(n, "y");
            sw.ori      = A(n, "ori");
            sw.addr     = AI(n, "addr");
            sw.port     = AI(n, "port");
            sw.protocol = A(n, "protocol");
            plan.switches.push_back(sw);
        }
        else if (tag == "sg") {
            PlanSignal sg;
            sg.id      = A(n, "id");
            sg.x       = AI(n, "x");
            sg.y       = AI(n, "y");
            sg.ori     = A(n, "ori");
            sg.blockId = A(n, "blockid");
            plan.signals.push_back(sg);
        }
        else if (tag == "rt") {
            PlanRoute rt;
            rt.id        = A(n, "id");
            rt.fromBlock = A(n, "fromblock");
            rt.toBlock   = A(n, "toblock");
            for (wxXmlNode* sw = n->GetChildren(); sw; sw = sw->GetNext()) {
                if (sw->GetName() == "sw") {
                    RouteSwitchCmd cmd;
                    cmd.switchId = A(sw, "id");
                    cmd.cmd      = A(sw, "cmd");
                    rt.switchCmds.push_back(cmd);
                }
            }
            plan.routes.push_back(rt);
        }
    }
    return true;
}

} // namespace MC
