#include "color.h"

#include <algorithm>
#include <array>
#include <vector>

// --- 辅助函数 ---

// 将单个十六进制字符转换为整数 (0-15)
int hex_char_to_int(char c) {
	if (c >= '0' && c <= '9') {
		return c - '0';
	}
	if (c >= 'a' && c <= 'f') {
		return c - 'a' + 10;
	}
	if (c >= 'A' && c <= 'F') {
		return c - 'A' + 10;
	}
	return -1;
}

// 去除字符串首尾空格
std::string trim_whitespace(const std::string& str) {
    size_t first = str.find_first_not_of(" \t\n\r\f\v");
    if (std::string::npos == first) {
        return str; // String contains only whitespace
    }
    size_t last = str.find_last_not_of(" \t\n\r\f\v");
    return str.substr(first, (last - first + 1));
}

// 按分隔符分割字符串
std::vector<std::string> split_string(const std::string& str, char delimiter) {
    std::vector<std::string> tokens;
    std::string token;
    std::istringstream tokenStream(str);
    while (std::getline(tokenStream, token, delimiter)) {
        tokens.push_back(token);
    }
    return tokens;
}


// --- 十六进制格式解析辅助函数 (保持不变) ---
std::optional<linear_color> parse_hex_color(const std::string& in_str) {
	const auto& hex_part = in_str.substr(1);
	const size_t length = hex_part.length();

	// 检查所有字符是否为有效十六进制数字 (使用 cctype::isxdigit)
	for (const char c: hex_part) {
		if (!::isxdigit(static_cast<unsigned char>(c))) { return std::nullopt; }
    }

	linear_color result{};

	// #RGB
	if (length == 3) {
		int r = hex_char_to_int(hex_part[0]);
		int g = hex_char_to_int(hex_part[1]);
		int b = hex_char_to_int(hex_part[2]);
		if (r == -1 || g == -1 || b == -1)
			return std::nullopt;
		result.r = (r * 16 + r) / 255.0f;
		result.g = (g * 16 + g) / 255.0f;
		result.b = (b * 16 + b) / 255.0f;
		result.a = 1.0f;
		return result;
	}
	// #RGBA
	if (length == 4) {
		int r = hex_char_to_int(hex_part[0]);
		int g = hex_char_to_int(hex_part[1]);
		int b = hex_char_to_int(hex_part[2]);
		int a = hex_char_to_int(hex_part[3]);
		if (r == -1 || g == -1 || b == -1 || a == -1)
			return std::nullopt;
		result.r = (r * 16 + r) / 255.0f;
		result.g = (g * 16 + g) / 255.0f;
		result.b = (b * 16 + b) / 255.0f;
		result.a = (a * 16 + a) / 255.0f;
		return result;
	}
	// #RRGGBB
	if (length == 6) {
		int r = (hex_char_to_int(hex_part[0]) << 4) + hex_char_to_int(hex_part[1]);
		int g = (hex_char_to_int(hex_part[2]) << 4) + hex_char_to_int(hex_part[3]);
		int b = (hex_char_to_int(hex_part[4]) << 4) + hex_char_to_int(hex_part[5]);
		if (r < 0 || g < 0 || b < 0)
			return std::nullopt; // Check hex_char_to_int results implicitly
		result.r = r / 255.0f;
		result.g = g / 255.0f;
		result.b = b / 255.0f;
		result.a = 1.0f;
		return result;
	}
	// #RRGGBBAA
	if (length == 8) {
		int r = (hex_char_to_int(hex_part[0]) << 4) + hex_char_to_int(hex_part[1]);
		int g = (hex_char_to_int(hex_part[2]) << 4) + hex_char_to_int(hex_part[3]);
		int b = (hex_char_to_int(hex_part[4]) << 4) + hex_char_to_int(hex_part[5]);
		int a = (hex_char_to_int(hex_part[6]) << 4) + hex_char_to_int(hex_part[7]);
		if (r < 0 || g < 0 || b < 0 || a < 0)
			return std::nullopt; // Check hex_char_to_int results implicitly
		result.r = r / 255.0f;
		result.g = g / 255.0f;
		result.b = b / 255.0f;
		result.a = a / 255.0f;
		return result;
	}
	return std::nullopt;
}

// --- RGB/RGBA 格式解析辅助函数 (重写为手动解析) ---
std::optional<linear_color> parse_rgb_rgba_color(const std::string& in_str) {
    std::string lower_str = in_str;
    // 转换为小写以便检查 "rgb(" 和 "rgba("
    std::ranges::transform(lower_str, lower_str.begin(), [](const char c) {
    	return static_cast<char>(tolower(c));
    });

    const auto open_paren = lower_str.find('(');
    const auto close_paren = lower_str.find(')');

    if (open_paren == std::string::npos || close_paren == std::string::npos || close_paren <= open_paren) {
        return std::nullopt; // 括号不匹配或顺序错误
    }

    const auto& prefix  = lower_str.substr(0, open_paren);
    const bool  is_rgba = prefix == "rgba";
    const bool  is_rgb  = prefix == "rgb";

    if (!is_rgb && !is_rgba) {
        return std::nullopt; // 前缀不是 rgb 或 rgba
    }

    // **提取括号内的内容**
    const auto& content = in_str.substr(open_paren + 1, close_paren - open_paren - 1);

    // **按逗号分割**
    const auto& components_str = split_string(content, ',');
    const auto expected_components = is_rgba ? 4uz : 3uz;

    if (components_str.size() != expected_components) {
        return std::nullopt; // 组件数量不正确
    }

	std::array<float, 4> components;
	auto index = 0uz;
    bool uses_float = false;
    bool uses_int = false;

    for (const std::string& comp_str_raw : components_str) {
        // **去除每个组件的首尾空格**
        const auto& comp_str = trim_whitespace(comp_str_raw);
        if (comp_str.empty()) {
            return std::nullopt; // 空组件
        }

        try {
            // **检查是否包含小数点，以此判断是浮点数还是整数**
            if (comp_str.find('.') != std::string::npos || comp_str.find('e') != std::string::npos || comp_str.find('E') != std::string::npos) {
	            // **尝试解析为浮点数**
	            const auto val_f = std::stof(comp_str);
            	components[index] = val_f;
                uses_float = true;
            } else {
                // **尝试解析为整数**
                const auto val_i  = std::stoi(comp_str);
            	components[index] = static_cast<float>(val_i);
                uses_int          = true;
            }
        	index++;
        } catch (const std::invalid_argument&) {
            return std::nullopt; // 无法解析为数字
        } catch (const std::out_of_range&) {
            return std::nullopt; // 数字超出范围 (stoi/stof)
        }
    }

    // **不允许混合整数和浮点数格式**
    if (uses_float && uses_int) {
        // 一个特例：允许整数 0 或 1 出现在浮点数格式中，视为 0.0f 或 1.0f
        // 但这里为了简化，我们严格区分，要么全是类整数，要么全是类浮点数
        // 如果需要支持混合，需要更复杂的逻辑判断每个分量
        return std::nullopt;
    }

    linear_color result{};

    if (uses_float) {
	    if (index != expected_components)
		    return std::nullopt; // 应该不会发生，但作为保险
        result.r = components[0];
        result.g = components[1];
        result.b = components[2];
        result.a = is_rgba ? components[3] : 1.0f;
        return result;
    }

    if (uses_int) {
	    if (index != expected_components)
		    return std::nullopt; // 应该不会发生
        result.r = components[0] / 255.0f;
        result.g = components[1] / 255.0f;
        result.b = components[2] / 255.0f;
        result.a = is_rgba ? components[3] / 255.0f : 1.0f;
        return result;
    }

    // **如果既没有解析出浮点数也没有解析出整数 (例如空字符串)，则失败**
    return std::nullopt;
}


// --- linear_color 静态成员函数实现 ---
std::optional<linear_color> linear_color::from_string(const std::string& in_str) {
	if (in_str.empty()) { return std::nullopt; }

	// **去除首尾空格**
	std::string trimmed_str = trim_whitespace(in_str);
	if (trimmed_str.empty()) { return std::nullopt; }

	// **委托给十六进制解析器**
	if (trimmed_str[0] == '#') {
		// **支持的十六进制格式:** #RGB, #RGBA, #RRGGBB, #RRGGBBAA
		return parse_hex_color(trimmed_str);
	}

	std::string lower_trimmed_str = trimmed_str;
	std::ranges::transform(lower_trimmed_str, lower_trimmed_str.begin(), [](const char c) {
		return static_cast<char>(tolower(c));
	});

	// **委托给 RGB/RGBA 解析器**
	if (lower_trimmed_str.rfind("rgb", 0) == 0) {
		// 检查是否以 "rgb" 或 "rgba" 开头
		// **支持的 RGB/RGBA 格式 (包括整数和浮点数，以及内部空格):**
		// - rgb(r,g,b)
		// - rgba(r,g,b,a)
		return parse_rgb_rgba_color(trimmed_str); // 传递原始带大小写的字符串给解析器
	}

	// **未知格式**
	return std::nullopt;
}
