#pragma once
/**
 * @file color.h
 * @brief 定义表示线性色彩空间的颜色类
 *
 * 本文件定义了linear_color类，用于在线性色彩空间中表示和操作颜色值。
 * 提供了颜色创建、转换和操作的功能。
 */

#include <complex>

/**
 * @class linear_color
 * @brief 线性色彩空间中的颜色表示
 *
 * 表示RGBA颜色，存储在线性色彩空间中。提供了从sRGB色彩空间转换到线性空间的功能，
 * 以及基本的颜色算术操作。线性色彩空间适合进行颜色混合和数学运算。
 */
class linear_color {
public:
    //-------------- 构造函数 --------------

    /**
     * @brief 默认构造函数，创建白色不透明颜色
     */
    linear_color() : r(1), g(1), b(1), a(1) {
    }

    /**
     * @brief 从RGBA分量构造颜色
     * @param in_r 红色分量 [0,1]
     * @param in_g 绿色分量 [0,1]
     * @param in_b 蓝色分量 [0,1]
     * @param in_a 透明度 [0,1]，默认为不透明
     *
     * 直接使用提供的值构造线性颜色，不进行色彩空间转换。
     */
    linear_color(float in_r, float in_g, float in_b, float in_a = 1.0f) : r(in_r), g(in_g), b(in_b), a(in_a) {
    }

    //-------------- 静态创建方法 --------------

    /**
     * @brief 从sRGB颜色空间创建线性颜色
     * @param in_r sRGB红色分量 [0,1]
     * @param in_g sRGB绿色分量 [0,1]
     * @param in_b sRGB蓝色分量 [0,1]
     * @param in_a 透明度 [0,1]，默认为不透明
     * @return 转换到线性空间的颜色
     *
     * 将sRGB颜色空间的值转换到线性颜色空间。透明度不进行转换。
     */
    static linear_color from_srgb(float in_r, float in_g, float in_b, float in_a = 1.0f) {
	    return {
		    in_r <= 0.04045f ? in_r / 12.92f : std::pow((in_r + 0.055f) / 1.055f, 2.4f),
		    in_g <= 0.04045f ? in_g / 12.92f : std::pow((in_g + 0.055f) / 1.055f, 2.4f),
		    in_b <= 0.04045f ? in_b / 12.92f : std::pow((in_b + 0.055f) / 1.055f, 2.4f),
		    in_a
	    };
    }

    /**
     * @brief 从sRGB颜色对象创建线性颜色
     * @param in_color 源sRGB颜色
     * @return 转换到线性空间的颜色
     *
     * 将一个表示sRGB值的颜色对象转换到线性颜色空间。
     */
    static linear_color from_srgb(const linear_color& in_color) {
        return from_srgb(in_color.r, in_color.g, in_color.b, in_color.a);
    }

    //-------------- 操作符重载 --------------

    /**
     * @brief 颜色加法，就地操作
     * @param in_color 要添加的颜色
     * @return 结果颜色的引用
     *
     * 将另一个颜色添加到当前颜色。
     */
    linear_color& operator+=(const linear_color& in_color) {
        r += in_color.r;
        g += in_color.g;
        b += in_color.b;
        a += in_color.a;
        return *this;
    }

    /**
     * @brief 颜色减法，就地操作
     * @param in_color 要减去的颜色
     * @return 结果颜色的引用
     *
     * 从当前颜色中减去另一个颜色。
     */
    linear_color& operator-=(const linear_color& in_color) {
        r -= in_color.r;
        g -= in_color.g;
        b -= in_color.b;
        a -= in_color.a;
        return *this;
    }

    /**
     * @brief 颜色加法
     * @param in_color 要添加的颜色
     * @return 新的结果颜色
     *
     * 创建一个新的颜色，表示两个颜色的和。
     */
    linear_color operator+(const linear_color& in_color) const {
        return { r + in_color.r, g + in_color.g, b + in_color.b, a + in_color.a };
    }

    /**
     * @brief 颜色减法
     * @param in_color 要减去的颜色
     * @return 新的结果颜色
     *
     * 创建一个新的颜色，表示当前颜色减去提供的颜色。
     */
    linear_color operator-(const linear_color& in_color) const {
        return { r - in_color.r, g - in_color.g, b - in_color.b, a - in_color.a };
    }

    /**
     * @brief 颜色相等比较
     * @param in_color 要比较的颜色
     * @return 如果颜色相等则返回true
     *
     * 检查两个颜色是否完全相等。
     */
    bool operator==(const linear_color& in_color) const {
        return r == in_color.r && g == in_color.g && b == in_color.b && a == in_color.a;
    }

    //-------------- 成员变量 --------------

    /** 红色分量，范围 [0,1] */
    float r;

    /** 绿色分量，范围 [0,1] */
    float g;

    /** 蓝色分量，范围 [0,1] */
    float b;

    /** 透明度，范围 [0,1]，1表示不透明 */
    float a;

    //-------------- 静态常量 --------------

    /** 白色: (1,1,1,1) */
    static linear_color white() { return {1.0f, 1.0f, 1.0f, 1.0f }; }

    /** 黑色: (0,0,0,1) */
    static linear_color black() { return { 0.0f, 0.0f, 0.0f, 1.0f }; }

    /** 透明色: (0,0,0,0) */
    static linear_color transparent() { return { 0.0f, 0.0f, 0.0f, 1.0f }; }
};
