/*
 * Copyright (C) 2016 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.content.res;

import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Resources.Theme;

import com.android.internal.R;
import com.android.internal.util.GrowingArrayUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.graphics.LinearGradient;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;

import java.io.IOException;


public class GradientColor extends ComplexColor {
    private static final String TAG = "GradientColor";

    private static final boolean DBG_GRADIENT = false;

    /** Lazily-created factory for this GradientColor. */
    private GradientColorFactory mFactory;

    private int mChangingConfigurations;
    private int mDefaultColor;

    // After parsing all the attributes from XML, this shader is the ultimate result containing
    // all the XML information.
    private Shader mShader = null;

    // Below are the attributes at the root element <gradient>
    private int mGradientType = GradientDrawable.LINEAR_GRADIENT;

    private float mCenterX = 0f;
    private float mCenterY = 0f;

    private float mStartX = 0f;
    private float mStartY = 0f;
    private float mEndX = 0f;
    private float mEndY = 0f;

    private int mStartColor = 0;
    private int mCenterColor = 0;
    private int mEndColor = 0;
    private boolean mHasCenterColor = false;

    private float mGradientRadius = 0f;

    // Below are the attributes for the <item> element.
    private int[] mItemColors;
    private float[] mItemOffsets;

    // Theme attributes for the root and item elements.
    private int[] mThemeAttrs;
    private int[][] mItemsThemeAttrs;

    private GradientColor() {
    }

    private GradientColor(GradientColor copy) {
        if (copy != null) {
            mChangingConfigurations = copy.mChangingConfigurations;
            mDefaultColor = copy.mDefaultColor;
            mShader = copy.mShader;
            mGradientType = copy.mGradientType;
            mCenterX = copy.mCenterX;
            mCenterY = copy.mCenterY;
            mStartX = copy.mStartX;
            mStartY = copy.mStartY;
            mEndX = copy.mEndX;
            mEndY = copy.mEndY;
            mStartColor = copy.mStartColor;
            mCenterColor = copy.mCenterColor;
            mEndColor = copy.mEndColor;
            mHasCenterColor = copy.mHasCenterColor;
            mGradientRadius = copy.mGradientRadius;

            if (copy.mItemColors != null) {
                mItemColors = copy.mItemColors.clone();
            }
            if (copy.mItemOffsets != null) {
                mItemOffsets = copy.mItemOffsets.clone();
            }

            if (copy.mThemeAttrs != null) {
                mThemeAttrs = copy.mThemeAttrs.clone();
            }
            if (copy.mItemsThemeAttrs != null) {
                mItemsThemeAttrs = copy.mItemsThemeAttrs.clone();
            }
        }
    }

    /**
     * Update the root level's attributes, either for inflate or applyTheme.
     */
    private void updateRootElementState(TypedArray a) {
        // Extract the theme attributes, if any.
        mThemeAttrs = a.extractThemeAttrs();

        mStartX = a.getFloat(
                R.styleable.GradientColor_startX, mStartX);
        mStartY = a.getFloat(
                R.styleable.GradientColor_startY, mStartY);
        mEndX = a.getFloat(
                R.styleable.GradientColor_endX, mEndX);
        mEndY = a.getFloat(
                R.styleable.GradientColor_endY, mEndY);

        mCenterX = a.getFloat(
                R.styleable.GradientColor_centerX, mCenterX);
        mCenterY = a.getFloat(
                R.styleable.GradientColor_centerY, mCenterY);

        mGradientType = a.getInt(
                R.styleable.GradientColor_type, mGradientType);

        mStartColor = a.getColor(
                R.styleable.GradientColor_startColor, mStartColor);
        mHasCenterColor |= a.hasValue(
                R.styleable.GradientColor_centerColor);
        mCenterColor = a.getColor(
                R.styleable.GradientColor_centerColor, mCenterColor);
        mEndColor = a.getColor(
                R.styleable.GradientColor_endColor, mEndColor);

        if (DBG_GRADIENT) {
            Log.v(TAG, "hasCenterColor is " + mHasCenterColor);
            if (mHasCenterColor) {
                Log.v(TAG, "centerColor:" + mCenterColor);
            }
            Log.v(TAG, "startColor: " + mStartColor);
            Log.v(TAG, "endColor: " + mEndColor);
        }

        mGradientRadius = a.getFloat(R.styleable.GradientColor_gradientRadius,
                mGradientRadius);
    }

    /**
     * Check if the XML content is valid.
     *
     * @throws XmlPullParserException if errors were found.
     */
    private void validateXmlContent() throws XmlPullParserException {
        if (mGradientRadius <= 0
                && mGradientType == GradientDrawable.RADIAL_GRADIENT) {
            throw new XmlPullParserException(
                    "<gradient> tag requires 'gradientRadius' "
                            + "attribute with radial type");
        }
    }

    /**
     * The shader information will be applied to the native VectorDrawable's path.
     * @hide
     */
    public Shader getShader() {
        return mShader;
    }

    /**
     * A public method to create GradientColor from a XML resource.
     */
    public static GradientColor createFromXml(Resources r, XmlResourceParser parser, Theme theme)
            throws XmlPullParserException, IOException {
        final AttributeSet attrs = Xml.asAttributeSet(parser);

        int type;
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
            // Seek parser to start tag.
        }

        if (type != XmlPullParser.START_TAG) {
            throw new XmlPullParserException("No start tag found");
        }

        return createFromXmlInner(r, parser, attrs, theme);
    }

    /**
     * Create from inside an XML document. Called on a parser positioned at a
     * tag in an XML document, tries to create a GradientColor from that tag.
     *
     * @return A new GradientColor for the current tag.
     * @throws XmlPullParserException if the current tag is not &lt;gradient>
     */
    @NonNull
    static GradientColor createFromXmlInner(@NonNull Resources r,
            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
            throws XmlPullParserException, IOException {
        final String name = parser.getName();
        if (!name.equals("gradient")) {
            throw new XmlPullParserException(
                    parser.getPositionDescription() + ": invalid gradient color tag " + name);
        }

        final GradientColor gradientColor = new GradientColor();
        gradientColor.inflate(r, parser, attrs, theme);
        return gradientColor;
    }

    /**
     * Fill in this object based on the contents of an XML "gradient" element.
     */
    private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
            @NonNull AttributeSet attrs, @Nullable Theme theme)
            throws XmlPullParserException, IOException {
        final TypedArray a = Resources.obtainAttributes(r, theme, attrs, R.styleable.GradientColor);
        updateRootElementState(a);
        mChangingConfigurations |= a.getChangingConfigurations();
        a.recycle();

        // Check correctness and throw exception if errors found.
        validateXmlContent();

        inflateChildElements(r, parser, attrs, theme);

        onColorsChange();
    }

    /**
     * Inflates child elements "item"s for each color stop.
     *
     * Note that at root level, we need to save ThemeAttrs for theme applied later.
     * Here similarly, at each child item, we need to save the theme's attributes, and apply theme
     * later as applyItemsAttrsTheme().
     */
    private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser,
            @NonNull AttributeSet attrs, @NonNull Theme theme)
            throws XmlPullParserException, IOException {
        final int innerDepth = parser.getDepth() + 1;
        int type;
        int depth;

        // Pre-allocate the array with some size, for better performance.
        float[] offsetList = new float[20];
        int[] colorList = new int[offsetList.length];
        int[][] themeAttrsList = new int[offsetList.length][];

        int listSize = 0;
        boolean hasUnresolvedAttrs = false;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && ((depth = parser.getDepth()) >= innerDepth
                || type != XmlPullParser.END_TAG)) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
            if (depth > innerDepth || !parser.getName().equals("item")) {
                continue;
            }

            final TypedArray a = Resources.obtainAttributes(r, theme, attrs,
                    R.styleable.GradientColorItem);
            boolean hasColor = a.hasValue(R.styleable.GradientColorItem_color);
            boolean hasOffset = a.hasValue(R.styleable.GradientColorItem_offset);
            if (!hasColor || !hasOffset) {
                throw new XmlPullParserException(
                        parser.getPositionDescription()
                                + ": <item> tag requires a 'color' attribute and a 'offset' "
                                + "attribute!");
            }

            final int[] themeAttrs = a.extractThemeAttrs();
            int color = a.getColor(R.styleable.GradientColorItem_color, 0);
            float offset = a.getFloat(R.styleable.GradientColorItem_offset, 0);

            if (DBG_GRADIENT) {
                Log.v(TAG, "new item color " + color + " " + Integer.toHexString(color));
                Log.v(TAG, "offset" + offset);
            }
            mChangingConfigurations |= a.getChangingConfigurations();
            a.recycle();

            if (themeAttrs != null) {
                hasUnresolvedAttrs = true;
            }

            colorList = GrowingArrayUtils.append(colorList, listSize, color);
            offsetList = GrowingArrayUtils.append(offsetList, listSize, offset);
            themeAttrsList = GrowingArrayUtils.append(themeAttrsList, listSize, themeAttrs);
            listSize++;
        }
        if (listSize > 0) {
            if (hasUnresolvedAttrs) {
                mItemsThemeAttrs = new int[listSize][];
                System.arraycopy(themeAttrsList, 0, mItemsThemeAttrs, 0, listSize);
            } else {
                mItemsThemeAttrs = null;
            }

            mItemColors = new int[listSize];
            mItemOffsets = new float[listSize];
            System.arraycopy(colorList, 0, mItemColors, 0, listSize);
            System.arraycopy(offsetList, 0, mItemOffsets, 0, listSize);
        }
    }

    /**
     * Apply theme to all the items.
     */
    private void applyItemsAttrsTheme(Theme t) {
        if (mItemsThemeAttrs == null) {
            return;
        }

        boolean hasUnresolvedAttrs = false;

        final int[][] themeAttrsList = mItemsThemeAttrs;
        final int N = themeAttrsList.length;
        for (int i = 0; i < N; i++) {
            if (themeAttrsList[i] != null) {
                final TypedArray a = t.resolveAttributes(themeAttrsList[i],
                        R.styleable.GradientColorItem);

                // Extract the theme attributes, if any, before attempting to
                // read from the typed array. This prevents a crash if we have
                // unresolved attrs.
                themeAttrsList[i] = a.extractThemeAttrs(themeAttrsList[i]);
                if (themeAttrsList[i] != null) {
                    hasUnresolvedAttrs = true;
                }

                mItemColors[i] = a.getColor(R.styleable.GradientColorItem_color, mItemColors[i]);
                mItemOffsets[i] = a.getFloat(R.styleable.GradientColorItem_offset, mItemOffsets[i]);
                if (DBG_GRADIENT) {
                    Log.v(TAG, "applyItemsAttrsTheme Colors[i] " + i + " " +
                            Integer.toHexString(mItemColors[i]));
                    Log.v(TAG, "Offsets[i] " + i + " " + mItemOffsets[i]);
                }

                // Account for any configuration changes.
                mChangingConfigurations |= a.getChangingConfigurations();

                a.recycle();
            }
        }

        if (!hasUnresolvedAttrs) {
            mItemsThemeAttrs = null;
        }
    }

    private void onColorsChange() {
        int[] tempColors = null;
        float[] tempOffsets = null;

        if (mItemColors != null) {
            int length = mItemColors.length;
            tempColors = new int[length];
            tempOffsets = new float[length];

            for (int i = 0; i < length; i++) {
                tempColors[i] = mItemColors[i];
                tempOffsets[i] = mItemOffsets[i];
            }
        } else {
            if (mHasCenterColor) {
                tempColors = new int[3];
                tempColors[0] = mStartColor;
                tempColors[1] = mCenterColor;
                tempColors[2] = mEndColor;

                tempOffsets = new float[3];
                tempOffsets[0] = 0.0f;
                // Since 0.5f is default value, try to take the one that isn't 0.5f
                tempOffsets[1] = 0.5f;
                tempOffsets[2] = 1f;
            } else {
                tempColors = new int[2];
                tempColors[0] = mStartColor;
                tempColors[1] = mEndColor;
            }
        }
        if (tempColors.length < 2) {
            Log.w(TAG, "<gradient> tag requires 2 color values specified!" + tempColors.length
                    + " " + tempColors);
        }

        if (mGradientType == GradientDrawable.LINEAR_GRADIENT) {
            mShader = new LinearGradient(mStartX, mStartY, mEndX, mEndY, tempColors, tempOffsets,
                    Shader.TileMode.CLAMP);
        } else {
            if (mGradientType == GradientDrawable.RADIAL_GRADIENT) {
                mShader = new RadialGradient(mCenterX, mCenterY, mGradientRadius, tempColors,
                        tempOffsets, Shader.TileMode.CLAMP);
            } else {
                mShader = new SweepGradient(mCenterX, mCenterY, tempColors, tempOffsets);
            }
        }
        mDefaultColor = tempColors[0];
    }

    /**
     * For Gradient color, the default color is not very useful, since the gradient will override
     * the color information anyway.
     */
    @Override
    @ColorInt
    public int getDefaultColor() {
        return mDefaultColor;
    }

    /**
     * Similar to ColorStateList, setup constant state and its factory.
     * @hide only for resource preloading
     */
    @Override
    public ConstantState<ComplexColor> getConstantState() {
        if (mFactory == null) {
            mFactory = new GradientColorFactory(this);
        }
        return mFactory;
    }

    private static class GradientColorFactory extends ConstantState<ComplexColor> {
        private final GradientColor mSrc;

        public GradientColorFactory(GradientColor src) {
            mSrc = src;
        }

        @Override
        public int getChangingConfigurations() {
            return mSrc.mChangingConfigurations;
        }

        @Override
        public GradientColor newInstance() {
            return mSrc;
        }

        @Override
        public GradientColor newInstance(Resources res, Theme theme) {
            return mSrc.obtainForTheme(theme);
        }
    }

    /**
     * Returns an appropriately themed gradient color.
     *
     * @param t the theme to apply
     * @return a copy of the gradient color the theme applied, or the
     * gradient itself if there were no unresolved theme
     * attributes
     * @hide only for resource preloading
     */
    @Override
    public GradientColor obtainForTheme(Theme t) {
        if (t == null || !canApplyTheme()) {
            return this;
        }

        final GradientColor clone = new GradientColor(this);
        clone.applyTheme(t);
        return clone;
    }

    private void applyTheme(Theme t) {
        if (mThemeAttrs != null) {
            applyRootAttrsTheme(t);
        }
        if (mItemsThemeAttrs != null) {
            applyItemsAttrsTheme(t);
        }
        onColorsChange();
    }

    private void applyRootAttrsTheme(Theme t) {
        final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.GradientColor);
        // mThemeAttrs will be set to null if if there are no theme attributes in the
        // typed array.
        mThemeAttrs = a.extractThemeAttrs(mThemeAttrs);
        // merging the attributes update inside the updateRootElementState().
        updateRootElementState(a);

        // Account for any configuration changes.
        mChangingConfigurations |= a.getChangingConfigurations();
        a.recycle();
    }


    /**
     * Returns whether a theme can be applied to this gradient color, which
     * usually indicates that the gradient color has unresolved theme
     * attributes.
     *
     * @return whether a theme can be applied to this gradient color.
     * @hide only for resource preloading
     */
    @Override
    public boolean canApplyTheme() {
        return mThemeAttrs != null || mItemsThemeAttrs != null;
    }

}
