/*
 * Copyright (C) 2016 Bilibili
 *
 * 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 com.bilibili.magicasakura.utils;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;

import com.bilibili.magicasakura.R;

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

import java.io.IOException;

/**
 * @author [email protected]
 * @time 16/3/17
 */
class LayerDrawableInflateImpl implements DrawableInflateDelegate {
    static final int STEP = 1;

    static final int[] ATTRS = new int[]{
            android.R.attr.left, android.R.attr.top, android.R.attr.right,
            android.R.attr.bottom, android.R.attr.id};

    @Override
    public Drawable inflateDrawable(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException {
        final int innerDepth = parser.getDepth() + 1;
        int type;
        int depth;
        int layerAttrUseCount = 0;
        int drawableUseCount = 0;
        int space = STEP << 1;
        //L,T,R,B,S,E,id
        int[][] childLayersAttrs = new int[space][ATTRS.length];
        Drawable[] drawables = new Drawable[space];

        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;
            }

            if (layerAttrUseCount >= childLayersAttrs.length) {
                int[][] dstInt = new int[drawables.length + STEP][ATTRS.length];
                System.arraycopy(childLayersAttrs, 0, dstInt, 0, childLayersAttrs.length);
                childLayersAttrs = dstInt;
            }
            updateLayerAttrs(context, attrs, childLayersAttrs[layerAttrUseCount]);
            layerAttrUseCount++;

            Drawable drawable = DrawableUtils.getAttrDrawable(context, attrs, android.R.attr.drawable);

            // If the layer doesn't have a drawable or unresolved theme
            // attribute for a drawable, attempt to parse one from the child
            // element.
            if (drawable == null) {
                while ((type = parser.next()) == XmlPullParser.TEXT) {
                }
                if (type != XmlPullParser.START_TAG) {
                    throw new XmlPullParserException(parser.getPositionDescription()
                            + ": <item> tag requires a 'drawable' attribute or "
                            + "child tag defining a drawable");
                }
                drawable = DrawableUtils.createFromXmlInner(context, parser, attrs);
            } else {
                final ColorStateList cls = DrawableUtils.getTintColorList(context, attrs, R.attr.drawableTint);
                if (cls != null) {
                    drawable = ThemeUtils.tintDrawable(drawable, cls, DrawableUtils.getTintMode(context, attrs, R.attr.drawableTintMode));
                }
            }

            if (drawable != null) {
                if (drawableUseCount >= drawables.length) {
                    Drawable[] dst = new Drawable[drawables.length + STEP];
                    System.arraycopy(drawables, 0, dst, 0, drawables.length);
                    drawables = dst;
                }
                drawables[drawableUseCount] = drawable;
                drawableUseCount++;
            }
        }

        if (drawables[0] == null || drawableUseCount != layerAttrUseCount) {
            return null;
        } else {
            LayerDrawable layerDrawable = new LayerDrawable(drawables);
            for (int i = 0; i < drawables.length; i++) {
                int[] childLayersAttr = childLayersAttrs[i];
                if (childLayersAttr[0] != 0 || childLayersAttr[1] != 0 || childLayersAttr[2] != 0 || childLayersAttr[3] != 0) {
                    layerDrawable.setLayerInset(i, childLayersAttr[0], childLayersAttr[1], childLayersAttr[2], childLayersAttr[3]);
                }
                if (childLayersAttr[4] != 0) {
                    layerDrawable.setId(i, childLayersAttr[4]);
                }
            }
            return layerDrawable;
        }
    }

    void updateLayerAttrs(Context context, AttributeSet attrs, int[] childLayersAttrs) {
        childLayersAttrs[0] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[0]);
        childLayersAttrs[1] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[1]);
        childLayersAttrs[2] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[2]);
        childLayersAttrs[3] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[3]);
        childLayersAttrs[4] = DrawableUtils.getAttrResourceId(context, attrs, ATTRS[4], 0);
    }
}