#include "canvas/CanvasState.h"
#include "io/CatalogLoader.h"
#include <sstream>

namespace MC {

// Map PieceType to plan.xml 'type' string
static std::string PieceTypeToXml(PieceType t) {
    switch (t) {
        case PieceType::Straight:        return "straight";
        case PieceType::Curve:           return "curve";
        case PieceType::TurnoutLeft:     return "straight"; // track type in plan.xml
        case PieceType::TurnoutRight:    return "straight";
        case PieceType::TurnoutY:        return "straight";
        case PieceType::DoubleCrossover: return "dcrossing";
        case PieceType::Bumper:          return "dir";
        case PieceType::Uncoupler:       return "straight";
        default:                         return "straight";
    }
}

// Map PieceType to plan.xml switch 'type' string
static std::string SwitchTypeToXml(PieceType t) {
    switch (t) {
        case PieceType::TurnoutLeft:     return "left";
        case PieceType::TurnoutRight:    return "right";
        case PieceType::TurnoutY:        return "threeway";
        case PieceType::DoubleCrossover: return "dcrossing";
        default:                         return "left";
    }
}

static bool IsTurnout(PieceType t) {
    return t == PieceType::TurnoutLeft  ||
           t == PieceType::TurnoutRight ||
           t == PieceType::TurnoutY     ||
           t == PieceType::DoubleCrossover;
}

RocrailPlan CanvasState::BuildPlan() const {
    RocrailPlan plan;

    auto& catalog = GetCatalog();
    int tkIdx = 1, swIdx = 1;

    for (const auto& placed : pieces) {
        const TrackPiece* def = catalog.Find(placed.catalogNumber);
        if (!def) continue;

        // Quantize world position to grid
        GridCell cell = quantizer.ToGrid(placed.transform.pos);
        std::string ori = GridQuantizer::QuantizeOrientation(
                              placed.transform.heading);

        if (IsTurnout(def->type)) {
            // ── Switch / Turnout ────────────────────────────────────────
            PlanSwitch sw;
            std::ostringstream id;
            id << "sw" << swIdx++;
            sw.id       = id.str();
            sw.type     = SwitchTypeToXml(def->type);
            sw.x        = cell.x;
            sw.y        = cell.y;
            sw.ori      = ori;
            sw.addr     = placed.dccAddress;
            sw.port     = placed.dccPort;
            sw.protocol = placed.protocol;
            plan.switches.push_back(sw);

            // Also add as a track piece so the diagram panel renders it
            PlanTrack tk;
            tk.id   = sw.id + "_tk";
            tk.x    = cell.x;
            tk.y    = cell.y;
            tk.type = "straight";
            tk.ori  = ori;
            plan.tracks.push_back(tk);
        }
        else {
            // ── Regular track piece ─────────────────────────────────────
            PlanTrack tk;
            std::ostringstream id;
            id << "tk" << tkIdx++;
            tk.id   = id.str();
            tk.x    = cell.x;
            tk.y    = cell.y;
            tk.type = PieceTypeToXml(def->type);
            tk.ori  = ori;
            plan.tracks.push_back(tk);
        }
    }

    return plan;
}

} // namespace MC
