/*
 * 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;

import com.android.ide.common.rendering.api.ILayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.graphics.Shader.TileMode;

import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
import java.awt.image.Raster;
import java.awt.image.SampleModel;

/**
 * Delegate implementing the native methods of android.graphics.RadialGradient
 *
 * Through the layoutlib_create tool, the original native methods of RadialGradient have been
 * replaced by calls to methods of the same name in this delegate class.
 *
 * This class behaves like the original native implementation, but in Java, keeping previously
 * native data into its own objects and mapping them to int that are sent back and forth between
 * it and the original RadialGradient class.
 *
 * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
 * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
 *
 * @see Shader_Delegate
 *
 */
public class RadialGradient_Delegate extends Gradient_Delegate {

    // ---- delegate data ----
    private java.awt.Paint mJavaPaint;

    // ---- Public Helper methods ----

    @Override
    public java.awt.Paint getJavaPaint() {
        return mJavaPaint;
    }

    // ---- native methods ----

    @LayoutlibDelegate
    /*package*/ static long nativeCreate(long matrix, float x, float y, float radius,
            long[] colors, float[] positions, int tileMode, long colorSpaceHandle) {
        RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(matrix, x, y, radius,
                colors, positions, Shader_Delegate.getTileMode(tileMode));
        return sManager.addNewDelegate(newDelegate);
    }

    // ---- Private delegate/helper methods ----

    /**
     * Create a shader that draws a radial gradient given the center and radius.
     *
     * @param nativeMatrix reference to the shader's native transformation matrix
     * @param x The x-coordinate of the center of the radius
     * @param y The y-coordinate of the center of the radius
     * @param radius Must be positive. The radius of the circle for this
     *            gradient
     * @param colors The colors to be distributed between the center and edge of
     *            the circle
     * @param positions May be NULL. The relative position of each corresponding
     *            color in the colors array. If this is NULL, the the colors are
     *            distributed evenly between the center and edge of the circle.
     * @param tile The Shader tiling mode
     */
    private RadialGradient_Delegate(long nativeMatrix, float x, float y, float radius,
            long[] colors, float[] positions, TileMode tile) {
        super(nativeMatrix, colors, positions);
        mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile);
    }

    private class RadialGradientPaint extends GradientPaint {

        private final float mX;
        private final float mY;
        private final float mRadius;

        public RadialGradientPaint(float x, float y, float radius,
                int[] colors, float[] positions, TileMode mode) {
            super(colors, positions, mode);
            mX = x;
            mY = y;
            mRadius = radius;
        }

        @Override
        public java.awt.PaintContext createContext(
                java.awt.image.ColorModel     colorModel,
                java.awt.Rectangle            deviceBounds,
                java.awt.geom.Rectangle2D     userBounds,
                java.awt.geom.AffineTransform xform,
                java.awt.RenderingHints       hints) {
            precomputeGradientColors();

            java.awt.geom.AffineTransform canvasMatrix;
            try {
                canvasMatrix = xform.createInverse();
            } catch (java.awt.geom.NoninvertibleTransformException e) {
                Bridge.getLog().fidelityWarning(ILayoutLog.TAG_MATRIX_INVERSE,
                        "Unable to inverse matrix in RadialGradient", e, null, null /*data*/);
                canvasMatrix = new java.awt.geom.AffineTransform();
            }

            java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
            try {
                localMatrix = localMatrix.createInverse();
            } catch (java.awt.geom.NoninvertibleTransformException e) {
                Bridge.getLog().fidelityWarning(ILayoutLog.TAG_MATRIX_INVERSE,
                        "Unable to inverse matrix in RadialGradient", e, null, null /*data*/);
                localMatrix = new java.awt.geom.AffineTransform();
            }

            return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel);
        }

        private class RadialGradientPaintContext implements java.awt.PaintContext {

            private final java.awt.geom.AffineTransform mCanvasMatrix;
            private final java.awt.geom.AffineTransform mLocalMatrix;
            private final java.awt.image.ColorModel mColorModel;

            public RadialGradientPaintContext(
                    java.awt.geom.AffineTransform canvasMatrix,
                    java.awt.geom.AffineTransform localMatrix,
                    java.awt.image.ColorModel colorModel) {
                mCanvasMatrix = canvasMatrix;
                mLocalMatrix = localMatrix;
                mColorModel = colorModel.hasAlpha() ? colorModel : ColorModel.getRGBdefault();
            }

            @Override
            public void dispose() {
            }

            @Override
            public java.awt.image.ColorModel getColorModel() {
                return mColorModel;
            }

            @Override
            public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
                int[] data = new int[w*h];

                // compute distance from each point to the center, and figure out the distance from
                // it.
                int index = 0;
                float[] pt1 = new float[2];
                float[] pt2 = new float[2];

                for (int iy = 0 ; iy < h ; iy++) {
                    for (int ix = 0 ; ix < w ; ix++) {
                        // handle the canvas transform
                        pt1[0] = x + ix;
                        pt1[1] = y + iy;
                        mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);

                        // handle the local matrix
                        pt1[0] = pt2[0];
                        pt1[1] = pt2[1];
                        mLocalMatrix.transform(pt1, 0, pt2, 0, 1);

                        float _x = pt2[0] - mX;
                        float _y = pt2[1] - mY;
                        float distance = (float) Math.hypot(_x, _y);

                        data[index++] = getGradientColor(distance / mRadius);
                    }
                }

                DataBufferInt dataBuffer = new DataBufferInt(data, data.length);
                SampleModel colorModel = mColorModel.createCompatibleSampleModel(w, h);
                return Raster.createWritableRaster(colorModel, dataBuffer, null);
            }

        }
    }

}
