/*
 * Copyright (c) 2002, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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 String PENDING = "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 (StateInfo state : states) {
                buf.append(state.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 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();
        }
    }
}
