/*
 * 				Twidere - Twitter client for Android
 * 
 *  Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program 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 for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.mariotaku.twidere.view.iface;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.GravityCompat;
import androidx.core.view.ViewCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;

import org.mariotaku.twidere.R;

public interface IForegroundView {

    /**
     * Returns the drawable used as the foreground of this FrameLayout. The
     * foreground drawable, if non-null, is always drawn on top of the children.
     *
     * @return A Drawable or null if no foreground was set.
     */
    Drawable getForeground();

    /**
     * Supply a Drawable that is to be rendered on top of all of the child views
     * in the frame layout. Any padding in the Drawable will be taken into
     * account by ensuring that the children are inset to be placed inside of
     * the padding area.
     *
     * @param drawable The Drawable to be drawn on top of the children.
     */
    void setForeground(final Drawable drawable);

    /**
     * Describes how the foreground is positioned. Defaults to START and TOP.
     *
     * @param foregroundGravity See {@link android.view.Gravity}
     */
    void setForegroundGravity(int foregroundGravity);

    class ForegroundViewHelper {

        private final View mView;

        private final Rect mSelfBounds = new Rect();
        private final Rect mOverlayBounds = new Rect();

        private Drawable mForeground;

        private int mForegroundGravity = Gravity.FILL;
        private boolean mForegroundInPadding = true;
        private boolean mForegroundBoundsChanged = false;

        public ForegroundViewHelper(final View view, final Context context, final AttributeSet attrs, final int defStyle) {
            mView = view;
            final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView, defStyle, 0);

            mForegroundGravity = a.getInt(R.styleable.ForegroundView_android_foregroundGravity, mForegroundGravity);

            final Drawable d = a.getDrawable(R.styleable.ForegroundView_android_foreground);
            if (d != null) {
                setForeground(d);
            }

//            mForegroundInPadding = true;

            a.recycle();
        }

        public void dispatchDrawableHotspotChanged(float x, float y) {
            if (mForeground == null) return;
            DrawableCompat.setHotspot(mForeground, x, y);
        }

        public void dispatchOnDraw(final Canvas canvas) {
            draw(canvas);
        }

        public void draw(Canvas canvas) {
            final Drawable foreground = mForeground;
            if (foreground == null) return;

            if (mForegroundBoundsChanged) {
                mForegroundBoundsChanged = false;
                final Rect selfBounds = mSelfBounds;
                final Rect overlayBounds = mOverlayBounds;

                final int w = mView.getRight() - mView.getLeft();
                final int h = mView.getBottom() - mView.getTop();

                if (mForegroundInPadding) {
                    selfBounds.set(0, 0, w, h);
                } else {
                    selfBounds.set(mView.getPaddingLeft(), mView.getPaddingTop(), w - mView.getPaddingRight(), h
                            - mView.getPaddingBottom());
                }

                final int layoutDirection = ViewCompat.getLayoutDirection(mView);
                GravityCompat.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, layoutDirection);
                foreground.setBounds(overlayBounds);
            }

            foreground.draw(canvas);
        }

        public void dispatchOnLayout(final boolean changed, final int left, final int top, final int right,
                                     final int bottom) {
            mForegroundBoundsChanged = true;
        }

        public void dispatchOnSizeChanged(final int w, final int h, final int oldw, final int oldh) {
            mForegroundBoundsChanged = true;
        }

        public void drawableStateChanged() {
            if (mForeground != null && mForeground.isStateful()) {
                mForeground.setState(mView.getDrawableState());
            }
        }

        public Drawable getForeground() {
            return mForeground;
        }

        public void setForeground(final Drawable drawable) {
            if (mForeground != drawable) {
                if (mForeground != null) {
                    mForeground.setCallback(null);
                    mView.unscheduleDrawable(mForeground);
                }

                mForeground = drawable;

                if (drawable != null) {
                    drawable.setCallback(mView);
                    if (drawable.isStateful()) {
                        drawable.setState(mView.getDrawableState());
                    }
                    if (mForegroundGravity == Gravity.FILL) {
                        final Rect padding = new Rect();
                        if (drawable.getPadding(padding)) {
                        }
                    }
                }
                mView.requestLayout();
                mView.invalidate();
            }
        }

        public void jumpDrawablesToCurrentState() {
            if (mForeground != null) {
                mForeground.jumpToCurrentState();
            }
        }

        public void setForegroundGravity(int foregroundGravity) {
            if (mForegroundGravity != foregroundGravity) {
                if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
                    foregroundGravity |= Gravity.START;
                }

                if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
                    foregroundGravity |= Gravity.TOP;
                }

                mForegroundGravity = foregroundGravity;

                if (mForegroundGravity == Gravity.FILL && mForeground != null) {
                    final Rect padding = new Rect();
                    if (mForeground.getPadding(padding)) {
                    }
                } else {
                }

                mView.requestLayout();
            }
        }

        public boolean verifyDrawable(final Drawable who) {
            return who == mForeground;
        }
    }
}
