#include "colors.h"

void interpolateLinearly(hsv_t start, hsv_t end, size_t steps, hsv_t *colors) {
	if( steps == 1 ) {
		colors[0] = start;
		return;
	}

	for( size_t i = 0; i < steps; i++ ) {
		hsv_t tmp;
		tmp.hue = (uint16_t)((int16_t)start.hue + ((int16_t)end.hue - (int16_t)start.hue) * (int16_t)i / ((int16_t)steps-1));
		tmp.sat = (uint8_t)((int16_t)start.sat + ((int16_t)end.sat - (int16_t)start.sat) * (int16_t)i / ((int16_t)steps-1));
		tmp.val = (uint8_t)((int16_t)start.val + ((int16_t)end.val - (int16_t)start.val) * (int16_t)i / ((int16_t)steps-1));
		colors[i] = tmp;
	}
}

void hsv2rgbList(hsv_t* hsv, rgb_t* rgb, size_t count) {
	for(size_t i = 0; i < count; ++i) {
		rgb[i] = hsv2rgb(&hsv[i]);
	}
}

rgb_t hsv2rgb(hsv_t* hsv) {
	rgb_t res;
	
	if(hsv->sat == 0) {
		res.r = res.g = res.b = hsv->val;
	} else {
		float hue  = (float) (hsv->hue<360?hsv->hue:hsv->hue-360);
		float val  = ((float) hsv->val ) / 100.0;
		float sat  = ((float) hsv->sat ) / 100.0;
		           
		uint8_t h  = hue / 60;
		float f    = ( hue / 60 ) - h;
		 
		 uint8_t p = RGB_MAX * ( val * ( 1 - sat ));
		 uint8_t q = RGB_MAX * ( val * ( 1 - sat * f ));
		 uint8_t t = RGB_MAX * ( val * ( 1 - sat * ( 1 - f )));
		
		switch(h) {
			case 0:
			case 6: res.r = hsv->val; 	res.g = t; 			res.b = p; break;
			case 1: res.r = q; 			res.g = hsv->val; 	res.b = p; break;
			case 2: res.r = p;		 	res.g = hsv->val; 	res.b = t; break;
			case 3: res.r = p; 			res.g = q; 			res.b = hsv->val; break;
			case 4: res.r = t;		 	res.g = p; 			res.b = hsv->val; break;
			case 5: res.r = hsv->hue; 	res.g = p; 			res.b = q; break;
			
		}
	}
	return res;
}

hsv_t makeHSV(uint16_t hue, uint8_t sat, uint8_t val) {
	hsv_t tmp;
	tmp.hue = hue;
	tmp.sat = sat;
	tmp.val = val;
	
	return tmp;
}
