#!/bin/zsh
setopt no_unset warn_create_global
hsl_to_rgb() {
    local Hue=$1 Saturation=$2 Luminance=$3
    local R G B
    local temp1 temp2
    local tempR tempG tempB

    if (( Hue < 0 || Hue > 1)); then
        printf >&2 '%s\n' "$0: error: Hue out of range: ${(qqq)Hue}"
        return 2
    fi

    if (( Saturation < 0 || Saturation > 1)); then
        printf >&2 '%s\n' "$0: error: Saturation out of range: ${(qqq)Saturation}"
        return 2
    fi

    if (( Luminance < 0 || Luminance > 1)); then
        printf >&2 '%s\n' "$0: error: Luminance out of range: ${(qqq)Luminance}"
        return 2
    fi

    if ((Saturation == 0)) ; then
        R=$Luminance
        G=$Luminance
        B=$Luminance
        printf '#%02x%02x%02x\n' $(( R * 255 )) $(( G * 255 )) $(( B * 255 ))
        return 0
    fi

    if ((Luminance < 0.5)) ; then
        temp1=$(( Luminance * (1 + Saturation) ))
    else
        temp1=$(( Luminance + Saturation - Luminance * Saturation ))
    fi

    temp2=$(( 2 * Luminance - temp1 ))

    #Hue=$(( Hue / 360 ))

    tempR=$(( Hue + 0.333 ))
    tempG=$(( Hue ))
    tempB=$(( Hue - 0.333 ))

    if ((tempR < 0)); then
        tempR=$(( tempR + 1 ))
    fi
    if ((tempR > 1)); then
        tempR=$(( tempR - 1 ))
    fi
    if ((tempG < 0)); then
        tempG=$(( tempG + 1 ))
    fi
    if ((tempG > 1)); then
        tempG=$(( tempG - 1 ))
    fi
    if ((tempB < 0)); then
        tempB=$(( tempB + 1 ))
    fi
    if ((tempB > 1)); then
        tempB=$(( tempB - 1 ))
    fi

    if ((6 * tempR < 1)); then
        R=$(( temp2 + (temp1 - temp2) * 6 * tempR ))
    else
        if ((2 * tempR < 1)); then
            R=$(( temp1 ))
        else
            if ((3 * tempR < 2)); then
                R=$(( temp2 + (temp1 - temp2) * (0.666 - tempR) * 6 ))
            else
                R=$(( temp2 ))
            fi
        fi
    fi

    if ((6 * tempG < 1)); then
        G=$(( temp2 + (temp1 - temp2) * 6 * tempG ))
    else
        if ((2 * tempG < 1)); then
            G=$(( temp1 ))
        else
            if ((3 * tempG < 2)); then
                G=$(( temp2 + (temp1 - temp2) * (0.666 - tempG) * 6 ))
            else
                G=$(( temp2 ))
            fi
        fi
    fi


    if ((6 * tempB < 1)); then
        B=$(( temp2 + (temp1 - temp2) * 6 * tempB ))
    else
        if ((2 * tempB < 1)); then
            B=$(( temp1 ))
        else
            if ((3 * tempB < 2)); then
                B=$(( temp2 + (temp1 - temp2) * (0.666 - tempB) * 6 ))
            else
                B=$(( temp2 ))
            fi
        fi
    fi

    printf '#%02x%02x%02x\n' $(( R * 255 )) $(( G * 255 )) $(( B * 255 ))
}
#typeset -f -t hsl_to_rgb

hsl_to_rgb "$@"