/*
 * @(#)ColorUtil.java    $Revision: 1.9 $  $Date: 2007/10/03 04:39:39 $
 *
 * Copyright (C) 2007 Meldcraft Corporation
 *
 * This file is part of Scaffold.
 * 
 * Scaffold is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Scaffold is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Scaffold.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.meldcraft.util;

import java.awt.Color;
import java.text.DecimalFormat;
import java.util.StringTokenizer;

/**
 * Parse color strings:
 * <pre>
 *    #rrggbbaa   - hexadecimal values (alpha is optional)
 *    #rgba       - short-hand hexadecimal values (alpha is optional)
 *    .r,.g,.b,.a - decimal values, range 0 <= value <= 1.0 (alpha is optional)
 *    r,g,b,a     - integer values, range 0 <= value <= 255 (alpha is optional)
 *    name        - X windows color name
 * </pre>
 *
 * @version $Revision: 1.9 $ $Date: 2007/10/03 04:39:39 $
 * @author Rob Richards
 */
public class ColorUtil
{
    /**
     * Return the Color corresponding to color string.  Return null on
     * failure to decode color.
     */
    public static Color getColor(String color)
    {
        return getColor(color, null);
    }

    /**
     * Return the Color corresponding to color string.  Return defaultColor on
     * failure to decode color.
     */
    public static Color getColor(String color, Color defaultColor)
    {
        Color   col = defaultColor;

        if (color == null)
        {
            return col;
        }

        // web hex color
        if (color.charAt(0) == '#')
        {
            int r,g,b,a;
            try
            {
                if (color.length() > 5)
                {
                    // web style #rrggbb
                    r = Integer.decode("0x"+color.substring(1,3)).intValue();
                    g = Integer.decode("0x"+color.substring(3,5)).intValue();
                    b = Integer.decode("0x"+color.substring(5,7)).intValue();
                    if (color.length() >= 9)
                    {
                        a = Integer.decode("0x"+color.substring(7,9)).intValue();
                        col = new Color(r,g,b,a);
                    }
                    else
                    {
                        col = new Color(r,g,b);
                    }
                }
                else
                {
                    // css style #rbg
                    r = Integer.decode("0x"+color.substring(1,2)+
                                            color.substring(1,2)).intValue();
                    g = Integer.decode("0x"+color.substring(2,3)+
                                            color.substring(2,3)).intValue();
                    b = Integer.decode("0x"+color.substring(3,4)+
                                            color.substring(3,4)).intValue();
                    if (color.length() >= 5)
                    {
                        a = Integer.decode("0x"+color.substring(4,5)+
                                                color.substring(4,5)).intValue();
                        col = new Color(r,g,b,a);
                    }
                    else
                    {
                        col = new Color(r,g,b);
                    }
                }
            }
            catch (Exception e)
            {
                col = defaultColor;
            }
            return col;
        }

        // X windows color
        col = XColorUtil.getColor(color);
        if (col != null)
        {
            return col;
        }

        // .r,.g,.b,.a or r,g,b,a
        StringTokenizer tok = new StringTokenizer (color, ",");
        if ((tok.countTokens() != 3) && (tok.countTokens() != 4))
        {
            return defaultColor;
        }

        String red = tok.nextToken();
        String green = tok.nextToken();
        String blue = tok.nextToken();
        String alpha = null;
        if (tok.hasMoreTokens())
        {
            alpha = tok.nextToken();
        }

        // convert strings to floats
        float r,b,g,a=0.0f;
        try
        {
            r = Float.valueOf(red).floatValue();
            g = Float.valueOf(green).floatValue();
            b = Float.valueOf(blue).floatValue();
            if (alpha != null)
            {
                a = Float.valueOf(alpha).floatValue();
            }
        }
        catch (NumberFormatException e)
        {
            return defaultColor;
        }

        // create a new Color from these values
        try
        {
            boolean useFloats=true;
            if ((red.indexOf('.') < 0) &&
                (green.indexOf('.') < 0) &&
                (blue.indexOf('.') < 0) &&
                ((alpha == null) || (alpha.indexOf('.') < 0)))
            {
                useFloats=false;
            }

            if (useFloats)
            {
                if (alpha != null)
                {
                    //.r,.g,.b,.a
                    col = new Color(r,g,b,a);
                }
                else
                {
                    //.r,.g,.b
                    col = new Color(r,g,b);
                }
            }
            else
            {
                if (alpha != null)
                {
                    // r,g,b,a
                    col = new Color((int)r, (int)g, (int)b, (int)a);
                }
                else
                {
                    // r,g,b
                    col = new Color((int)r, (int)g, (int)b);
                }
            }
        }
        catch (Exception e)
        {
            col = defaultColor;
        }

        return col;
    }

    public static String asHexValues(Color color)
    {
        return asHexValues(color, false);
    }

    public static String asHexValues(Color color, boolean includeAlpha)
    {
        String colorStr = null;
        if (color != null)
        {
            int[] rgb = new int[] {color.getRed(),
                                   color.getGreen(),
                                   color.getBlue(),
                                   color.getAlpha()};

            colorStr = "#";
            int len = (includeAlpha && (rgb[3] != 255)) ? rgb.length : (rgb.length - 1);
            for (int i=0 ; i < len ; i++)
            {
                String str = Integer.toHexString(rgb[i]);
                if (str.length() < 2)
                {
                    str = "0" + str;
                }
                colorStr += str;
            }
        }
        return colorStr;
    }

    public static String asIntValues(Color color)
    {
        return asIntValues(color, false);
    }

    public static String asIntValues(Color color, boolean includeAlpha)
    {
        String ret = null;

        if (color != null)
        {
            ret = color.getRed() + "," + color.getGreen() + "," +
            color.getBlue(); 

            if (includeAlpha)
            {
               int alpha = color.getAlpha();
               if (alpha != 255)
               {
                   ret += "," + alpha;
               }
            }
        }

        return ret;
    }

    public static String asFloatValues(Color color)
    {
        return asFloatValues(color, false);
    }

    public static String asFloatValues(Color color, boolean includeAlpha)
    {
        String ret = null;
        
        if (color != null)
        {
            float[] vals;
            if (includeAlpha)
            {
                vals = color.getRGBComponents(null);
            }
            else
            {
                vals = color.getRGBColorComponents(null);
            }

            ret = "";

            DecimalFormat fmt = new DecimalFormat("0.000");
            for (int i=0 ; i < vals.length ; i++)
            {
                if ((i < 3) || (vals[i] != 1.0f))
                {
                    if (i > 0)
                    {
                        ret += ",";
                    }
                    ret += fmt.format(vals[i]);
                }
            }
        }

        return ret;
    }

    /** Decode all strings provided on command line and print the results. */
    public static void main (String args[])
    {
        for (int i=0 ; i < args.length ; i++)
        {
            StringBuffer buf = new StringBuffer(args[i] + ":");

            Color   col = ColorUtil.getColor(args[i]);
            if (col != null)
            {
                String name = XColorUtil.getXColorName(col);
                if (name == null)
                {
                    buf.append("\t<No X color name>.");
                }
                else
                {
                    buf.append("\tX color name: " + name + " = " + 
                                       XColorUtil.getColor(name));
                }

                buf.append("\t" + asHexValues(col, true) + " " +
                                  asIntValues(col, true) + " " +
                                  asFloatValues(col, true));
            }
            else
            {
                buf.append("\tNo match.");
            }

            System.out.println(buf);
        }
    }
}

