#ifndef PIXEL
#define PIXEL

#include "../define.h"
#include "../math/function.h"
#include "math.h"

namespace sleek
{
    namespace math
    {
        class pixel
        {
            public:
                pixel(const u32 color = 0xFFFFFFFF) noexcept
                {
                    blue =  (color >>  0) & 0xFF;
                    green = (color >>  8) & 0xFF;
                    red =   (color >> 16) & 0xFF;
                    alpha = (color >> 24) & 0xFF;
                }
                pixel(const u8 r, const u8 g, const u8 b,const u8 a = 255) noexcept
                {
                    red = r;
                    green = g;
                    blue = b;
                    alpha = a;
                }
                ~pixel() noexcept
                {
                }

                inline void set(const u8 r, const u8 g, const u8 b,const u8 a = 255) noexcept
                {
                    red = r;
                    green = g;
                    blue = b;
                    alpha = a;
                }

                inline void setRed(const u8 i) noexcept   { red = i;   }
                inline void setGreen(const u8 i) noexcept { green = i; }
                inline void setBlue(const u8 i) noexcept  { blue = i;  }
                inline void setAlpha(const u8 i) noexcept { alpha = i; }

                inline u8 getRed() const noexcept   { return red;   }
                inline u8 getGreen() const noexcept { return green; }
                inline u8 getBlue() const noexcept  { return blue;  }
                inline u8 getAlpha() const noexcept { return alpha; }

                inline pixel getInterpolated(const pixel &other, f32 d) const
                {
                    d = math::clamp(d, 0.f, 1.f);
                    const f32 inv = 1.0f - d;

                    return {
                        u8(other.red  *inv + red  *d),
                        u8(other.green*inv + green*d),
                        u8(other.blue *inv + blue *d),
                        u8(other.alpha*inv + alpha*d)
                    };
                }

                inline pixel monochrome() const noexcept
                {
                    pixel tmp = monochrome_with_alpha();
                    tmp.setAlpha(255);
                    return tmp;;
                }
                inline pixel monochrome_with_alpha() const noexcept
                {
                    u8 luminaissance = getLuminaissance();
                    return pixel(luminaissance,luminaissance,luminaissance,alpha);
                }
                inline u8 getLuminaissance() const noexcept
                {
                    return (red+green+blue)/3;
                }
            public:
                inline vec3f HSV() const noexcept
                {
                    math::vec3f hsv;

                    f32 M = math::max(getRed(), getGreen(), getBlue());
                    f32 m = math::min(getRed(), getGreen(), getBlue());
                    f32 C = M - m;

                    if(C == 0)
                        hsv.x = 0;
                    else if(M <= getRed())
                        hsv.x = (getGreen() - getBlue()) / C;
                    else if(M <= getGreen())
                        hsv.x = (getBlue() - getRed()) / C + 2;
                    else if(M <= getBlue())
                        hsv.x = (getRed() - getGreen()) / C + 4;

                    hsv.x *= 60;
                    if(hsv.x < 0)
                        hsv.x += 360;

                    hsv.y = M;
                    hsv.z = M == 0 ? 0 : C / hsv.y;

                    return hsv;
                }
            public:
                u8 red;
                u8 green;
                u8 blue;
                u8 alpha;
        };
    }
}

#endif