#include "rm_control/config/simple_json.h"

#include <cerrno>
#include <cstdlib>
#include <stdexcept>
#include <utility>

namespace rm_control::config {
namespace {

class Parser {
public:
    explicit Parser(const std::string &text)
        : text_(text) {}

    common::Result<JsonValue> parse() {
        skipWhitespace();
        auto value = parseValue();
        if (!value.ok) {
            return value;
        }

        skipWhitespace();
        if (pos_ != text_.size()) {
            return fail("unexpected trailing characters");
        }
        return value;
    }

private:
    common::Result<JsonValue> parseValue() {
        // JSON 值只在这里分发，后续新增类型时也只改这一处。
        skipWhitespace();
        if (pos_ >= text_.size()) {
            return fail("unexpected end of input");
        }

        const char ch = text_[pos_];
        if (ch == '{') {
            return parseObject();
        }
        if (ch == '[') {
            return parseArray();
        }
        if (ch == '"') {
            return parseString();
        }
        if (ch == '-' || (ch >= '0' && ch <= '9')) {
            return parseNumber();
        }
        if (matchLiteral("true")) {
            return common::Result<JsonValue>::success(JsonValue(true));
        }
        if (matchLiteral("false")) {
            return common::Result<JsonValue>::success(JsonValue(false));
        }
        if (matchLiteral("null")) {
            return common::Result<JsonValue>::success(JsonValue());
        }
        return fail("invalid JSON value");
    }

    common::Result<JsonValue> parseObject() {
        // 解析 { "key": value }。使用 std::map 存储，方便按字段名查找。
        ++pos_;
        JsonValue::Object object;
        skipWhitespace();
        if (consume('}')) {
            return common::Result<JsonValue>::success(JsonValue(std::move(object)));
        }

        while (true) {
            skipWhitespace();
            if (pos_ >= text_.size() || text_[pos_] != '"') {
                return fail("object key must be a string");
            }

            auto key = parseString();
            if (!key.ok) {
                return key;
            }

            skipWhitespace();
            if (!consume(':')) {
                return fail("expected ':' after object key");
            }

            auto value = parseValue();
            if (!value.ok) {
                return value;
            }

            object[key.value.asString()] = value.value;
            skipWhitespace();
            if (consume('}')) {
                break;
            }
            if (!consume(',')) {
                return fail("expected ',' or '}' in object");
            }
        }

        return common::Result<JsonValue>::success(JsonValue(std::move(object)));
    }

    common::Result<JsonValue> parseArray() {
        // 解析数组，命令文件里主要用于 joints_deg、delta_deg 和 pose。
        ++pos_;
        JsonValue::Array array;
        skipWhitespace();
        if (consume(']')) {
            return common::Result<JsonValue>::success(JsonValue(std::move(array)));
        }

        while (true) {
            auto value = parseValue();
            if (!value.ok) {
                return value;
            }
            array.push_back(value.value);

            skipWhitespace();
            if (consume(']')) {
                break;
            }
            if (!consume(',')) {
                return fail("expected ',' or ']' in array");
            }
        }

        return common::Result<JsonValue>::success(JsonValue(std::move(array)));
    }

    common::Result<JsonValue> parseString() {
        // 解析字符串并处理常见转义。unicode 转义当前只做合法性检查，
        // 因为命令字段名和数值不依赖中文字符串内容。
        if (!consume('"')) {
            return fail("expected string");
        }

        std::string output;
        while (pos_ < text_.size()) {
            const char ch = text_[pos_++];
            if (ch == '"') {
                return common::Result<JsonValue>::success(JsonValue(std::move(output)));
            }
            if (static_cast<unsigned char>(ch) < 0x20U) {
                return fail("control character in string");
            }
            if (ch != '\\') {
                output.push_back(ch);
                continue;
            }

            if (pos_ >= text_.size()) {
                return fail("unfinished escape sequence");
            }
            const char escaped = text_[pos_++];
            switch (escaped) {
            case '"':
            case '\\':
            case '/':
                output.push_back(escaped);
                break;
            case 'b':
                output.push_back('\b');
                break;
            case 'f':
                output.push_back('\f');
                break;
            case 'n':
                output.push_back('\n');
                break;
            case 'r':
                output.push_back('\r');
                break;
            case 't':
                output.push_back('\t');
                break;
            case 'u':
                // 命令文件字段名不需要 unicode 转义；这里跳过合法的 4 位十六进制并保留占位符。
                if (pos_ + 4 > text_.size()) {
                    return fail("unfinished unicode escape");
                }
                for (int i = 0; i < 4; ++i) {
                    const char hex = text_[pos_ + static_cast<size_t>(i)];
                    const bool valid = (hex >= '0' && hex <= '9') ||
                                       (hex >= 'a' && hex <= 'f') ||
                                       (hex >= 'A' && hex <= 'F');
                    if (!valid) {
                        return fail("invalid unicode escape");
                    }
                }
                pos_ += 4;
                output.push_back('?');
                break;
            default:
                return fail("invalid escape sequence");
            }
        }

        return fail("unterminated string");
    }

    common::Result<JsonValue> parseNumber() {
        // strtod 支持整数、小数和科学计数法；外层会继续检查是否有限值。
        const char *begin = text_.c_str() + pos_;
        char *end = nullptr;
        errno = 0;
        const double value = std::strtod(begin, &end);
        if (errno != 0 || end == begin) {
            return fail("invalid number");
        }
        pos_ = static_cast<size_t>(end - text_.c_str());
        return common::Result<JsonValue>::success(JsonValue(value));
    }

    bool matchLiteral(const char *literal) {
        const std::string token(literal);
        if (text_.compare(pos_, token.size(), token) != 0) {
            return false;
        }
        pos_ += token.size();
        return true;
    }

    bool consume(char expected) {
        if (pos_ < text_.size() && text_[pos_] == expected) {
            ++pos_;
            return true;
        }
        return false;
    }

    void skipWhitespace() {
        while (pos_ < text_.size()) {
            const char ch = text_[pos_];
            if (ch != ' ' && ch != '\n' && ch != '\r' && ch != '\t') {
                break;
            }
            ++pos_;
        }
    }

    common::Result<JsonValue> fail(const std::string &message) const {
        // 带上字节位置，方便用户定位 JSON 文件中的错误字段。
        return common::Result<JsonValue>::failure(message + " at byte " + std::to_string(pos_));
    }

    const std::string &text_;
    size_t pos_ = 0;
};

} // namespace

JsonValue::JsonValue(bool value)
    : type_(Type::Bool), bool_value_(value) {}

JsonValue::JsonValue(double value)
    : type_(Type::Number), number_value_(value) {}

JsonValue::JsonValue(std::string value)
    : type_(Type::String), string_value_(std::move(value)) {}

JsonValue::JsonValue(Array value)
    : type_(Type::Array), array_value_(std::move(value)) {}

JsonValue::JsonValue(Object value)
    : type_(Type::Object), object_value_(std::move(value)) {}

JsonValue::Type JsonValue::type() const {
    return type_;
}

bool JsonValue::isNull() const {
    return type_ == Type::Null;
}

bool JsonValue::isBool() const {
    return type_ == Type::Bool;
}

bool JsonValue::isNumber() const {
    return type_ == Type::Number;
}

bool JsonValue::isString() const {
    return type_ == Type::String;
}

bool JsonValue::isArray() const {
    return type_ == Type::Array;
}

bool JsonValue::isObject() const {
    return type_ == Type::Object;
}

bool JsonValue::asBool() const {
    if (!isBool()) {
        throw std::logic_error("JSON value is not a bool");
    }
    return bool_value_;
}

double JsonValue::asNumber() const {
    if (!isNumber()) {
        throw std::logic_error("JSON value is not a number");
    }
    return number_value_;
}

const std::string &JsonValue::asString() const {
    if (!isString()) {
        throw std::logic_error("JSON value is not a string");
    }
    return string_value_;
}

const JsonValue::Array &JsonValue::asArray() const {
    if (!isArray()) {
        throw std::logic_error("JSON value is not an array");
    }
    return array_value_;
}

const JsonValue::Object &JsonValue::asObject() const {
    if (!isObject()) {
        throw std::logic_error("JSON value is not an object");
    }
    return object_value_;
}

const JsonValue *JsonValue::find(const std::string &key) const {
    if (!isObject()) {
        return nullptr;
    }
    const auto iter = object_value_.find(key);
    return iter == object_value_.end() ? nullptr : &iter->second;
}

common::Result<JsonValue> parseJson(const std::string &text) {
    // 对外只暴露一个函数，避免调用方依赖 Parser 的内部状态。
    Parser parser(text);
    return parser.parse();
}

} // namespace rm_control::config
