/*
 * Copyright 2002-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package sun.swing.plaf.synth;

import javax.swing.plaf.synth.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.*;

/**
 * Default implementation of SynthStyle. Has setters for the various
 * SynthStyle methods. Many of the properties can be specified for all states,
 * using SynthStyle directly, or a specific state using one of the StateInfo
 * methods.
 * <p>
 * Beyond the constructor a subclass should override the <code>addTo</code>
 * and <code>clone</code> methods, these are used when the Styles are being
 * merged into a resulting style.
 *
 * @author Scott Violet
 */
public class DefaultSynthStyle extends SynthStyle implements Cloneable {
    private static final Object PENDING = new String("Pending");

    /**
     * Should the component be opaque?
     */
    private boolean opaque;
    /**
     * Insets.
     */
    private Insets insets;
    /**
     * Information specific to ComponentState.
     */
    private StateInfo[] states;
    /**
     * User specific data.
     */
    private Map data;

    /**
     * Font to use if there is no matching StateInfo, or the StateInfo doesn't
     * define one.
     */
    private Font font;

    /**
     * SynthGraphics, may be null.
     */
    private SynthGraphicsUtils synthGraphics;

    /**
     * Painter to use if the StateInfo doesn't have one.
     */
    private SynthPainter painter;


    /**
     * Nullary constructor, intended for subclassers.
     */
    public DefaultSynthStyle() {
    }

    /**
     * Creates a new DefaultSynthStyle that is a copy of the passed in
     * style. Any StateInfo's of the passed in style are clonsed as well.
     *
     * @param style Style to duplicate
     */
    public DefaultSynthStyle(DefaultSynthStyle style) {
        opaque = style.opaque;
        if (style.insets != null) {
            insets = new Insets(style.insets.top, style.insets.left,
                                style.insets.bottom, style.insets.right);
        }
        if (style.states != null) {
            states = new StateInfo[style.states.length];
            for (int counter = style.states.length - 1; counter >= 0;
                     counter--) {
                states[counter] = (StateInfo)style.states[counter].clone();
            }
        }
        if (style.data != null) {
            data = new HashMap();
            data.putAll(style.data);
        }
        font = style.font;
        synthGraphics = style.synthGraphics;
        painter = style.painter;
    }

    /**
     * Creates a new DefaultSynthStyle.
     *
     * @param insets Insets for the Style
     * @param opaque Whether or not the background is completely painted in
     *        an opaque color
     * @param states StateInfos describing properties per state
     * @param data Style specific data.
     */
    public DefaultSynthStyle(Insets insets, boolean opaque,
                             StateInfo[] states, Map data) {
        this.insets = insets;
        this.opaque = opaque;
        this.states = states;
        this.data = data;
    }

    public Color getColor(SynthContext context, ColorType type) {
        return getColor(context.getComponent(), context.getRegion(),
                        context.getComponentState(), type);
    }

    public Color getColor(JComponent c, Region id, int state,
                          ColorType type) {
        // For the enabled state, prefer the widget's colors
        if (!id.isSubregion() && state == SynthConstants.ENABLED) {
            if (type == ColorType.BACKGROUND) {
                return c.getBackground();
            }
            else if (type == ColorType.FOREGROUND) {
                return c.getForeground();
            }
            else if (type == ColorType.TEXT_FOREGROUND) {
                // If getForeground returns a non-UIResource it means the
                // developer has explicitly set the foreground, use it over
                // that of TEXT_FOREGROUND as that is typically the expected
                // behavior.
                Color color = c.getForeground();
                if (!(color instanceof UIResource)) {
                    return color;
                }
            }
        }
        // Then use what we've locally defined
        Color color = getColorForState(c, id, state, type);
        if (color == null) {
            // No color, fallback to that of the widget.
            if (type == ColorType.BACKGROUND ||
                        type == ColorType.TEXT_BACKGROUND) {
                return c.getBackground();
            }
            else if (type == ColorType.FOREGROUND ||
                     type == ColorType.TEXT_FOREGROUND) {
                return c.getForeground();
            }
        }
        return color;
    }

    protected Color getColorForState(SynthContext context, ColorType type) {
        return getColorForState(context.getComponent(), context.getRegion(),
                                context.getComponentState(), type);
    }

    /**
     * Returns the color for the specified state.
     *
     * @param c JComponent the style is associated with
     * @param id Region identifier
     * @param state State of the region.
     * @param type Type of color being requested.
     * @return Color to render with
     */
    protected Color getColorForState(JComponent c, Region id, int state,
                                     ColorType type) {
        // Use the best state.
        StateInfo si = getStateInfo(state);
        Color color;
        if (si != null && (color = si.getColor(type)) != null) {
            return color;
        }
        if (si == null || si.getComponentState() != 0) {
            si = getStateInfo(0);
            if (si != null) {
                return si.getColor(type);
            }
        }
        return null;
    }

    /**
     * Sets the font that is used if there is no matching StateInfo, or
     * it does not define a font.
     *
     * @param font Font to use for rendering
     */
    public void setFont(Font font) {
        this.font = font;
    }

    public Font getFont(SynthContext state) {
        return getFont(state.getComponent(), state.getRegion(),
                       state.getComponentState());
    }

    public Font getFont(JComponent c, Region id, int state) {
        if (!id.isSubregion() && state == SynthConstants.ENABLED) {
            return c.getFont();
        }
        Font cFont = c.getFont();
        if (cFont != null && !(cFont instanceof UIResource)) {
            return cFont;
        }
        return getFontForState(c, id, state);
    }

    /**
     * Returns the font for the specified state. This should NOT callback
     * to the JComponent.
     *
     * @param c JComponent the style is associated with
     * @param id Region identifier
     * @param state State of the region.
     * @return Font to render with
     */
    protected Font getFontForState(JComponent c, Region id, int state) {
        if (c == null) {
            return this.font;
        }
        // First pass, look for the best match
        StateInfo si = getStateInfo(state);
        Font font;
        if (si != null && (font = si.getFont()) != null) {
            return font;
        }
        if (si == null || si.getComponentState() != 0) {
            si = getStateInfo(0);
            if (si != null && (font = si.getFont()) != null) {
                return font;
            }
        }
        // Fallback font.
        return this.font;
    }

    protected Font getFontForState(SynthContext context) {
        return getFontForState(context.getComponent(), context.getRegion(),
                               context.getComponentState());
    }

    /**
     * Sets the SynthGraphicsUtils that will be used for rendering.
     *
     * @param graphics SynthGraphics
     */
    public void setGraphicsUtils(SynthGraphicsUtils graphics) {
        this.synthGraphics = graphics;
    }

    /**
     * Returns a SynthGraphicsUtils.
     *
     * @param context SynthContext indentifying requestor
     * @return SynthGraphicsUtils
     */
    public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
        if (synthGraphics == null) {
            return super.getGraphicsUtils(context);
        }
        return synthGraphics;
    }

    /**
     * Sets the insets.
     *
     * @param Insets.
     */
    public void setInsets(Insets insets) {
        this.insets = insets;
    }

    /**
     * Returns the Insets. If <code>to</code> is non-null the resulting
     * insets will be placed in it, otherwise a new Insets object will be
     * created and returned.
     *
     * @param context SynthContext indentifying requestor
     * @param to Where to place Insets
     * @return Insets.
     */
    public Insets getInsets(SynthContext state, Insets to) {
        if (to == null) {
            to = new Insets(0, 0, 0, 0);
        }
        if (insets != null) {
            to.left = insets.left;
            to.right = insets.right;
            to.top = insets.top;
            to.bottom = insets.bottom;
        }
        else {
            to.left = to.right = to.top = to.bottom = 0;
        }
        return to;
    }

    /**
     * Sets the Painter to use for the border.
     *
     * @param painter Painter for the Border.
     */
    public void setPainter(SynthPainter painter) {
        this.painter = painter;
    }

    /**
     * Returns the Painter for the passed in Component. This may return null.
     *
     * @param ss SynthContext indentifying requestor
     * @return Painter for the border
     */
    public SynthPainter getPainter(SynthContext ss) {
        return painter;
    }

    /**
     * Sets whether or not the JComponent should be opaque.
     *
     * @param opaque Whether or not the JComponent should be opaque.
     */
    public void setOpaque(boolean opaque) {
        this.opaque = opaque;
    }

    /**
     * Returns the value to initialize the opacity property of the Component
     * to. A Style should NOT assume the opacity will remain this value, the
     * developer may reset it or override it.
     *
     * @param ss SynthContext indentifying requestor
     * @return opaque Whether or not the JComponent is opaque.
     */
    public boolean isOpaque(SynthContext ss) {
        return opaque;
    }

    /**
     * Sets style specific values. This does NOT copy the data, it
     * assigns it directly to this Style.
     *
     * @param data Style specific values
     */
    public void setData(Map data) {
        this.data = data;
    }

    /**
     * Returns the style specific data.
     *
     * @return Style specific data.
     */
    public Map getData() {
        return data;
    }

    /**
     * Getter for a region specific style property.
     *
     * @param state SynthContext indentifying requestor
     * @param key Property being requested.
     * @return Value of the named property
     */
    public Object get(SynthContext state, Object key) {
        // Look for the best match
        StateInfo si = getStateInfo(state.getComponentState());
        if (si != null && si.getData() != null && getKeyFromData(si.getData(), key) != null) {
            return getKeyFromData(si.getData(), key);
        }
        si = getStateInfo(0);
        if (si != null && si.getData() != null && getKeyFromData(si.getData(), key) != null) {
            return getKeyFromData(si.getData(), key);
        }
        if(getKeyFromData(data, key) != null)
          return getKeyFromData(data, key);
        return getDefaultValue(state, key);
    }


    private Object getKeyFromData(Map stateData, Object key) {
          Object value = null;
          if (stateData != null) {

            synchronized(stateData) {
                value = stateData.get(key);
            }
            while (value == PENDING) {
                synchronized(stateData) {
                    try {
                        stateData.wait();
                    } catch (InterruptedException ie) {}
                    value = stateData.get(key);
                }
            }
            if (value instanceof UIDefaults.LazyValue) {
                synchronized(stateData) {
                    stateData.put(key, PENDING);
                }
                value = ((UIDefaults.LazyValue)value).createValue(null);
                synchronized(stateData) {
                    stateData.put(key, value);
                    stateData.notifyAll();
                }
            }
        }
        return value;
    }

    /**
     * Returns the default value for a particular property.  This is only
     * invoked if this style doesn't define a property for <code>key</code>.
     *
     * @param state SynthContext indentifying requestor
     * @param key Property being requested.
     * @return Value of the named property
     */
    public Object getDefaultValue(SynthContext context, Object key) {
        return super.get(context, key);
    }

    /**
     * Creates a clone of this style.
     *
     * @return Clone of this style
     */
    public Object clone() {
        DefaultSynthStyle style;
        try {
            style = (DefaultSynthStyle)super.clone();
        } catch (CloneNotSupportedException cnse) {
            return null;
        }
        if (states != null) {
            style.states = new StateInfo[states.length];
            for (int counter = states.length - 1; counter >= 0; counter--) {
                style.states[counter] = (StateInfo)states[counter].clone();
            }
        }
        if (data != null) {
            style.data = new HashMap();
            style.data.putAll(data);
        }
        return style;
    }

    /**
     * Merges the contents of this Style with that of the passed in Style,
     * returning the resulting merged syle. Properties of this
     * <code>DefaultSynthStyle</code> will take precedence over those of the
     * passed in <code>DefaultSynthStyle</code>. For example, if this
     * style specifics a non-null font, the returned style will have its
     * font so to that regardless of the <code>style</code>'s font.
     *
     * @param style Style to add our styles to
     * @return Merged style.
     */
    public DefaultSynthStyle addTo(DefaultSynthStyle style) {
        if (insets != null) {
            style.insets = this.insets;
        }
        if (font != null) {
            style.font = this.font;
        }
        if (painter != null) {
            style.painter = this.painter;
        }
        if (synthGraphics != null) {
            style.synthGraphics = this.synthGraphics;
        }
        style.opaque = opaque;
        if (states != null) {
            if (style.states == null) {
                style.states = new StateInfo[states.length];
                for (int counter = states.length - 1; counter >= 0; counter--){
                    if (states[counter] != null) {
                        style.states[counter] = (StateInfo)states[counter].
                                                clone();
                    }
                }
            }
            else {
                // Find the number of new states in unique, merging any
                // matching states as we go. Also, move any merge styles
                // to the end to give them precedence.
                int unique = 0;
                // Number of StateInfos that match.
                int matchCount = 0;
                int maxOStyles = style.states.length;
                for (int thisCounter = states.length - 1; thisCounter >= 0;
                         thisCounter--) {
                    int state = states[thisCounter].getComponentState();
                    boolean found = false;

                    for (int oCounter = maxOStyles - 1 - matchCount;
                             oCounter >= 0; oCounter--) {
                        if (state == style.states[oCounter].
                                           getComponentState()) {
                            style.states[oCounter] = states[thisCounter].
                                        addTo(style.states[oCounter]);
                            // Move StateInfo to end, giving it precedence.
                            StateInfo tmp = style.states[maxOStyles - 1 -
                                                         matchCount];
                            style.states[maxOStyles - 1 - matchCount] =
                                  style.states[oCounter];
                            style.states[oCounter] = tmp;
                            matchCount++;
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        unique++;
                    }
                }
                if (unique != 0) {
                    // There are states that exist in this Style that
                    // don't exist in the other style, recreate the array
                    // and add them.
                    StateInfo[] newStates = new StateInfo[
                                   unique + maxOStyles];
                    int newIndex = maxOStyles;

                    System.arraycopy(style.states, 0, newStates, 0,maxOStyles);
                    for (int thisCounter = states.length - 1; thisCounter >= 0;
                             thisCounter--) {
                        int state = states[thisCounter].getComponentState();
                        boolean found = false;

                        for (int oCounter = maxOStyles - 1; oCounter >= 0;
                                 oCounter--) {
                            if (state == style.states[oCounter].
                                               getComponentState()) {
                                found = true;
                                break;
                            }
                        }
                        if (!found) {
                            newStates[newIndex++] = (StateInfo)states[
                                      thisCounter].clone();
                        }
                    }
                    style.states = newStates;
                }
            }
        }
        if (data != null) {
            if (style.data == null) {
                style.data = new HashMap();
            }
            style.data.putAll(data);
        }
        return style;
    }

    /**
     * Sets the array of StateInfo's which are used to specify properties
     * specific to a particular style.
     *
     * @param states StateInfos
     */
    public void setStateInfo(StateInfo[] states) {
        this.states = states;
    }

    /**
     * Returns the array of StateInfo's that that are used to specify
     * properties specific to a particular style.
     *
     * @return Array of StateInfos.
     */
    public StateInfo[] getStateInfo() {
        return states;
    }

    /**
     * Returns the best matching StateInfo for a particular state.
     *
     * @param state Component state.
     * @return Best matching StateInfo, or null
     */
    public StateInfo getStateInfo(int state) {
        // Use the StateInfo with the most bits that matches that of state.
        // If there is none, than fallback to
        // the StateInfo with a state of 0, indicating it'll match anything.

        // Consider if we have 3 StateInfos a, b and c with states:
        // SELECTED, SELECTED | ENABLED, 0
        //
        // Input                          Return Value
        // -----                          ------------
        // SELECTED                       a
        // SELECTED | ENABLED             b
        // MOUSE_OVER                     c
        // SELECTED | ENABLED | FOCUSED   b
        // ENABLED                        c

        if (states != null) {
            int bestCount = 0;
            int bestIndex = -1;
            int wildIndex = -1;

            if (state == 0) {
                for (int counter = states.length - 1; counter >= 0;counter--) {
                    if (states[counter].getComponentState() == 0) {
                        return states[counter];
                    }
                }
                return null;
            }
            for (int counter = states.length - 1; counter >= 0; counter--) {
                int oState = states[counter].getComponentState();

                if (oState == 0) {
                    if (wildIndex == -1) {
                        wildIndex = counter;
                    }
                }
                else if ((state & oState) == oState) {
                    // This is key, we need to make sure all bits of the
                    // StateInfo match, otherwise a StateInfo with
                    // SELECTED | ENABLED would match ENABLED, which we
                    // don't want.

                    // This comes from BigInteger.bitCnt
                    int bitCount = oState;
                    bitCount -= (0xaaaaaaaa & bitCount) >>> 1;
                    bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) &
                                                      0x33333333);
                    bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f;
                    bitCount += bitCount >>> 8;
                    bitCount += bitCount >>> 16;
                    bitCount = bitCount & 0xff;
                    if (bitCount > bestCount) {
                        bestIndex = counter;
                        bestCount = bitCount;
                    }
                }
            }
            if (bestIndex != -1) {
                return states[bestIndex];
            }
            if (wildIndex != -1) {
                return states[wildIndex];
            }
          }
          return null;
    }


    public String toString() {
        StringBuffer buf = new StringBuffer();

        buf.append(super.toString()).append(',');

        buf.append("data=").append(data).append(',');

        buf.append("font=").append(font).append(',');

        buf.append("insets=").append(insets).append(',');

        buf.append("synthGraphics=").append(synthGraphics).append(',');

        buf.append("painter=").append(painter).append(',');

        StateInfo[] states = getStateInfo();
        if (states != null) {
            buf.append("states[");
            for (int i = 0; i < states.length; i++) {
                buf.append(states[i].toString()).append(',');
            }
            buf.append(']').append(',');
        }

        // remove last newline
        buf.deleteCharAt(buf.length() - 1);

        return buf.toString();
    }


    /**
     * StateInfo represents Style information specific to the state of
     * a component.
     */
    public static class StateInfo {
        private Map data;
        private Font font;
        private Color[] colors;
        private int state;

        /**
         * Creates a new StateInfo.
         */
        public StateInfo() {
        }

        /**
         * Creates a new StateInfo with the specified properties
         *
         * @param state Component state(s) that this StateInfo should be used
         * for
         * @param painter Painter responsible for rendering
         * @param bgPainter Painter responsible for rendering the background
         * @param font Font for this state
         * @param colors Colors for this state
         */
        public StateInfo(int state, Font font, Color[] colors) {
            this.state = state;
            this.font = font;
            this.colors = colors;
        }

        /**
         * Creates a new StateInfo that is a copy of the passed in
         * StateInfo.
         *
         * @param info StateInfo to copy.
         */
        public StateInfo(StateInfo info) {
            this.state = info.state;
            this.font = info.font;
            if(info.data != null) {
               if(data == null) {
                  data = new HashMap();
               }
               data.putAll(info.data);
            }
            if (info.colors != null) {
                this.colors = new Color[info.colors.length];
                System.arraycopy(info.colors, 0, colors, 0,info.colors.length);
            }
        }

        public Map getData() {
            return data;
        }

        public void setData(Map data) {
            this.data = data;
        }

        /**
         * Sets the font for this state.
         *
         * @param font Font to use for rendering
         */
        public void setFont(Font font) {
            this.font = font;
        }

        /**
         * Returns the font for this state.
         *
         * @return Returns the font to use for rendering this state
         */
        public Font getFont() {
            return font;
        }

        /**
         * Sets the array of colors to use for rendering this state. This
         * is indexed by <code>ColorType.getID()</code>.
         *
         * @param colors Array of colors
         */
        public void setColors(Color[] colors) {
            this.colors = colors;
        }

        /**
         * Returns the array of colors to use for rendering this state. This
         * is indexed by <code>ColorType.getID()</code>.
         *
         * @return Array of colors
         */
        public Color[] getColors() {
            return colors;
        }

        /**
         * Returns the Color to used for the specified ColorType.
         *
         * @return Color.
         */
        public Color getColor(ColorType type) {
            if (colors != null) {
                int id = type.getID();

                if (id < colors.length) {
                    return colors[id];
                }
            }
            return null;
        }

        /**
         * Merges the contents of this StateInfo with that of the passed in
         * StateInfo, returning the resulting merged StateInfo. Properties of
         * this <code>StateInfo</code> will take precedence over those of the
         * passed in <code>StateInfo</code>. For example, if this
         * StateInfo specifics a non-null font, the returned StateInfo will
         * have its font so to that regardless of the <code>StateInfo</code>'s
         * font.
         *
         * @param info StateInfo to add our styles to
         * @return Merged StateInfo.
         */
        public StateInfo addTo(StateInfo info) {
            if (font != null) {
                info.font = font;
            }
            if(data != null) {
                if(info.data == null) {
                    info.data = new HashMap();
                }
                info.data.putAll(data);
            }
            if (colors != null) {
                if (info.colors == null) {
                    info.colors = new Color[colors.length];
                    System.arraycopy(colors, 0, info.colors, 0,
                                     colors.length);
                }
                else {
                    if (info.colors.length < colors.length) {
                        Color[] old = info.colors;

                        info.colors = new Color[colors.length];
                        System.arraycopy(old, 0, info.colors, 0, old.length);
                    }
                    for (int counter = colors.length - 1; counter >= 0;
                             counter--) {
                        if (colors[counter] != null) {
                            info.colors[counter] = colors[counter];
                        }
                    }
                }
            }
            return info;
        }

        /**
         * Sets the state this StateInfo corresponds to.
         *
         * @see SynthConstants
         * @param state info.
         */
        public void setComponentState(int state) {
            this.state = state;
        }

        /**
         * Returns the state this StateInfo corresponds to.
         *
         * @see SynthConstants
         * @return state info.
         */
        public int getComponentState() {
            return state;
        }

        /**
         * Returns the number of states that are similar between the
         * ComponentState this StateInfo represents and val.
         */
        private final int getMatchCount(int val) {
            // This comes from BigInteger.bitCnt
            val &= state;
            val -= (0xaaaaaaaa & val) >>> 1;
            val = (val & 0x33333333) + ((val >>> 2) & 0x33333333);
            val = val + (val >>> 4) & 0x0f0f0f0f;
            val += val >>> 8;
            val += val >>> 16;
            return val & 0xff;
        }

        /**
         * Creates and returns a copy of this StateInfo.
         *
         * @return Copy of this StateInfo.
         */
        public Object clone() {
            return new StateInfo(this);
        }

        public String toString() {
            StringBuffer buf = new StringBuffer();

            buf.append(super.toString()).append(',');

            buf.append("state=").append(Integer.toString(state)).append(',');

            buf.append("font=").append(font).append(',');

            if (colors != null) {
                buf.append("colors=").append(Arrays.asList(colors)).
                    append(',');
            }
            return buf.toString();
        }
    }
}
