/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.graphics;


/**
 * Base class for Gradient shader. This is not a standard android class and is just used
 * as a base class for the re-implemented gradient classes.
 *
 * It also provides a base class to handle common code between the different shaders'
 * implementations of {@link java.awt.Paint}.
 *
 * @see LinearGradient
 * @see RadialGradient
 * @see SweepGradient
 */
public abstract class GradientShader extends Shader {

    protected final int[] mColors;
    protected final float[] mPositions;

    /**
     * Creates the base shader and do some basic test on the parameters.
     *
     * @param colors The colors to be distributed along the gradient line
     * @param positions May be null. The relative positions [0..1] of each
     *            corresponding color in the colors array. If this is null, the
     *            the colors are distributed evenly along the gradient line.
     */
    protected GradientShader(int colors[], float positions[]) {
        if (colors.length < 2) {
            throw new IllegalArgumentException("needs >= 2 number of colors");
        }
        if (positions != null && colors.length != positions.length) {
            throw new IllegalArgumentException("color and position arrays must be of equal length");
        }

        if (positions == null) {
            float spacing = 1.f / (colors.length - 1);
            positions = new float[colors.length];
            positions[0] = 0.f;
            positions[colors.length-1] = 1.f;
            for (int i = 1; i < colors.length - 1 ; i++) {
                positions[i] = spacing * i;
            }
        }

        mColors = colors;
        mPositions = positions;
    }

    /**
     * Base class for (Java) Gradient Paints. This handles computing the gradient colors based
     * on the color and position lists, as well as the {@link TileMode}
     *
     */
    protected abstract static class GradientPaint implements java.awt.Paint {
        private final static int GRADIENT_SIZE = 100;

        private final int[] mColors;
        private final float[] mPositions;
        private final TileMode mTileMode;
        private int[] mGradient;

        protected GradientPaint(int[] colors, float[] positions, TileMode tileMode) {
            mColors = colors;
            mPositions = positions;
            mTileMode = tileMode;
        }

        public int getTransparency() {
            return java.awt.Paint.TRANSLUCENT;
        }

        /**
         * Pre-computes the colors for the gradient. This must be called once before any call
         * to {@link #getGradientColor(float)}
         */
        protected synchronized void precomputeGradientColors() {
            if (mGradient == null) {
                // actually create an array with an extra size, so that we can really go
                // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0
                mGradient = new int[GRADIENT_SIZE+1];

                int prevPos = 0;
                int nextPos = 1;
                for (int i  = 0 ; i <= GRADIENT_SIZE ; i++) {
                    // compute current position
                    float currentPos = (float)i/GRADIENT_SIZE;
                    while (currentPos > mPositions[nextPos]) {
                        prevPos = nextPos++;
                    }

                    float percent = (currentPos - mPositions[prevPos]) /
                            (mPositions[nextPos] - mPositions[prevPos]);

                    mGradient[i] = computeColor(mColors[prevPos], mColors[nextPos], percent);
                }
            }
        }

        /**
         * Returns the color based on the position in the gradient.
         * <var>pos</var> can be anything, even &lt; 0 or &gt; > 1, as the gradient
         * will use {@link TileMode} value to convert it into a [0,1] value.
         */
        protected int getGradientColor(float pos) {
            if (pos < 0.f) {
                switch (mTileMode) {
                    case CLAMP:
                        pos = 0.f;
                        break;
                    case REPEAT:
                        // remove the integer part to stay in the [0,1] range
                        // careful: this is a negative value, so use ceil instead of floor
                        pos = pos - (float)Math.ceil(pos);
                        break;
                    case MIRROR:
                        // get the integer and the decimal part
                        // careful: this is a negative value, so use ceil instead of floor
                        int intPart = (int)Math.ceil(pos);
                        pos = pos - intPart;
                        // 0  -> -1 : mirrored order
                        // -1 -> -2: normal order
                        // etc..
                        // this means if the intpart is even we invert
                        if ((intPart % 2) == 0) {
                            pos = 1.f - pos;
                        }
                        break;
                }
            } else if (pos > 1f) {
                switch (mTileMode) {
                    case CLAMP:
                        pos = 1.f;
                        break;
                    case REPEAT:
                        // remove the integer part to stay in the [0,1] range
                        pos = pos - (float)Math.floor(pos);
                        break;
                    case MIRROR:
                        // get the integer and the decimal part
                        int intPart = (int)Math.floor(pos);
                        pos = pos - intPart;
                        // 0 -> 1 : normal order
                        // 1 -> 2: mirrored
                        // etc..
                        // this means if the intpart is odd we invert
                        if ((intPart % 2) == 1) {
                            pos = 1.f - pos;
                        }
                        break;
                }
            }

            int index = (int)((pos * GRADIENT_SIZE) + .5);

            return mGradient[index];
        }

        /**
         * Returns the color between c1, and c2, based on the percent of the distance
         * between c1 and c2.
         */
        private int computeColor(int c1, int c2, float percent) {
            int a = computeChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent);
            int r = computeChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent);
            int g = computeChannel((c1 >>  8) & 0xFF, (c2 >>  8) & 0xFF, percent);
            int b = computeChannel((c1      ) & 0xFF, (c2      ) & 0xFF, percent);
            return a << 24 | r << 16 | g << 8 | b;
        }

        /**
         * Returns the channel value between 2 values based on the percent of the distance between
         * the 2 values..
         */
        private int computeChannel(int c1, int c2, float percent) {
            return c1 + (int)((percent * (c2-c1)) + .5);
        }


    }
}
