#include "includes.h"

static const char* control_type[] = {"Voltage", "PWM"};
static const char* work_types[] = {"Glowing", "Blinking", "Breath"};

#define MASK_D 0xff000000
#define MASK_R 0x00ff0000
#define MASK_G 0x0000ff00
#define MASK_B 0x000000ff
#define SHIFT_D 24
#define SHIFT_R 16
#define SHIFT_G 8

#define MASK_F 0x0800
#define MASK_T 0x0600
#define MASK_E 0x01ff
#define SHIFT_F 11
#define SHIFT_T 9

rgbled* create_led() {
    rgbled* led = (rgbled*)malloc(sizeof(rgbled));
    set_Temp(led, 0);
    set_R(led, 0);
    set_D(led, 255);
    set_T(led, 0);
    set_F(led, 0);
    return led;
}

rgbled_bad* create_bad_led() {
    rgbled_bad* led = (rgbled_bad*)malloc(sizeof(rgbled_bad));
    return led;
}

void set_Temp(rgbled* led, int tempK) {
    if (tempK < 0 || tempK > 51200) return;
    tempK /= 100;
    int red, green, blue;
    if (tempK <= 66) {
        green = 99.4708025861 * log(tempK) - 161.1195681661;
        red = 255;
        if (tempK <= 19) {
            blue = 0;
        } else {
            blue = 138.5177312231 * log((tempK)-10) - 305.0447927307;
        }
    } else {
        red = 329.698727446 * powf((tempK-60), -0.1332047592);
        green = 288.1221695283 * powf((tempK - 60), -0.0755148492);
        blue = 255;
    }
    set_R(led, red);
    set_G(led, green);
    set_B(led, blue);
    led->efg = (led->efg & ~MASK_E) | ((tempK << 0) & MASK_E);
}

void set_R(rgbled* led, int red) {
    if (red < 0 || red > 255) return;
    led->rgbd = (led->rgbd & ~MASK_R) | ((red << SHIFT_R) & MASK_R);
    led->efg = (led->efg & ~MASK_E) | ((0) & MASK_E);
}

void set_G(rgbled* led, int green) {
    if (green < 0 || green > 255) return;
    led->rgbd = (led->rgbd & ~MASK_G) | ((green << SHIFT_G) & MASK_G);
    led->efg = (led->efg & ~MASK_E) | ((0) & MASK_E);
}

void set_B(rgbled* led, int blue) {
    if (blue < 0 || blue > 255) return;
    led->rgbd = (led->rgbd & ~MASK_B) | ((blue << 0) & MASK_B);
    led->efg = (led->efg & ~MASK_E) | ((0) & MASK_E);
}

void set_D(rgbled* led, int bright) {
    if (bright < 0 || bright > 255) return;
    led->rgbd = (led->rgbd & ~MASK_D) | ((bright << SHIFT_D) & MASK_D);
}

void set_T(rgbled* led, int work) {
    if (work < 0 || work > 3) return;
    led->efg = (led->efg & ~MASK_T) | ((work << SHIFT_T) & MASK_T);
}

void set_F(rgbled* led, int type) {
    if (type < 0 || type > 1) return;
    led->efg = (led->efg & ~MASK_F) | ((type << SHIFT_F) & MASK_F);
}

int get_Temp(rgbled* led) {
    return (led->efg & MASK_E)*100;
}

int get_R(rgbled* led) {
    return (led->rgbd & MASK_R) >> SHIFT_R;
}

int get_G(rgbled* led) {
    return (led->rgbd & MASK_G) >> SHIFT_G;
}

int get_B(rgbled* led) {
    return (led->rgbd & MASK_B);
}

int get_D(rgbled* led) {
    return (led->rgbd & MASK_D) >> SHIFT_D;
}

int get_F(rgbled* led) {
    return (led->efg & MASK_F) >> SHIFT_F;
}

int get_T(rgbled* led) {
    return (led->efg & MASK_T) >> SHIFT_T;
}

void hex_color(int num) {
    printf("%c%c", ((num/16) > 9) ? 'a'+(num / 16)-10 : '0'+(num/16), ((num%16) > 9) ? 'a'+(num%16)-10 : '0'+(num%16));
}

void print_colorHEX(rgbled* led) {
    int r = get_R(led)*(get_D(led)/255);
    int g = get_G(led)*(get_D(led)/255);
    int b = get_B(led)*(get_D(led)/255);
    //printf("(%d, %d, %d) ", r, g, b);
    putchar('#');
    hex_color(r);
    hex_color(g);
    hex_color(b);
}
