/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016  B. Stultiens
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
#ifndef __INC_HSV2RGB_H__
#define __INC_HSV2RGB_H__

#include <stdint.h>


typedef struct color_rgb {
    uint16_t r;
    uint16_t g;
    uint16_t b;
} color_rgb;

typedef struct color_hsv {
    uint16_t h;
    uint16_t s;
    uint16_t v;
} color_hsv;


#define HSV2RGB_BITS            8 // 10
#define HSV2RGB_COUNT           ((1 < HSV2RGB_BITS)-1)

#define HSV_HUE_SEXTANT         (1 << HSV2RGB_BITS)
#define HSV_HUE_STEPS           (6 * HSV_HUE_SEXTANT)

#define HSV_HUE_MIN             0
#define HSV_HUE_MAX             (HSV_HUE_STEPS - 1)
#define HSV_SAT_MIN             0
#define HSV_SAT_MAX             255
#define HSV_VAL_MIN             0
#define HSV_VAL_MAX             255

/* Options: */
#define HSV_USE_SEXTANT_TEST    /* Limit the hue to 0...360 degrees */

#define hsv2rgb(h,s,v,r,g,b)    hsv2rgb_32b_8(h,s,v,r,g,b)


//void hsv2rgb_8b(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b);
void hsv2rgb_32b_8(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b);
//void hsv2rgb_32b_16(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b);



/*
 * Macros that are common to all implementations
 */
#ifdef HSV_USE_SEXTANT_TEST
#define HSV_SEXTANT_TEST(sextant) \
    if((sextant) > 5) { \
        (sextant) = 5; \
    }

#else
#define HSV_SEXTANT_TEST(sextant)
#endif

/*
 * Pointer swapping:
 *  sext.   r g b   r<>b    g<>b    r <> g  result
 *  0 0 0   v u c           !u v c  u v c
 *  0 0 1   d v c               d v c
 *  0 1 0   c v u   u v c           u v c
 *  0 1 1   c d v   v d c       d v c   d v c
 *  1 0 0   u c v       u v c       u v c
 *  1 0 1   v c d       v d c   d v c   d v c
 *
 * if(sextant & 2)
 *  r <-> b
 *
 * if(sextant & 4)
 *  g <-> b
 *
 * if(!(sextant & 6) {
 *  if(!(sextant & 1))
 *      r <-> g
 * } else {
 *  if(sextant & 1)
 *      r <-> g
 * }
 */
#define HSV_SWAPPTR(a,b)    do { uint8_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
//#define HSV_SWAPPTR(a,b)    do { uint16_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
#define HSV_POINTER_SWAP(sextant,r,g,b) \
    do { \
        if((sextant) & 2) { \
            HSV_SWAPPTR((r), (b)); \
        } \
        if((sextant) & 4) { \
            HSV_SWAPPTR((g), (b)); \
        } \
        if(!((sextant) & 6)) { \
            if(!((sextant) & 1)) { \
                HSV_SWAPPTR((r), (g)); \
            } \
        } else { \
            if((sextant) & 1) { \
                HSV_SWAPPTR((r), (g)); \
            } \
        } \
    } while(0)
#define HSV_MONOCHROMATIC_TEST(s,v,r,g,b) \
    do { \
        if(!(s)) { \
             *(r) = *(g) = *(b) = (v); \
            return; \
        } \
    } while(0)



#endif
