package com.reactnativenavigation.views.sharedElementTransition;

import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.Keep;
import android.text.SpannableString;
import android.text.SpannedString;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewManager;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.view.DraweeView;
import com.facebook.react.views.image.ReactImageView;
import com.reactnativenavigation.params.parsers.SharedElementParamsParser;
import com.reactnativenavigation.params.parsers.SharedElementTransitionParams;
import com.reactnativenavigation.react.ReactViewHacks;
import com.reactnativenavigation.screens.Screen;
import com.reactnativenavigation.utils.Task;
import com.reactnativenavigation.utils.ViewUtils;
import com.reactnativenavigation.views.utils.ColorUtils;
import com.reactnativenavigation.views.utils.PathPoint;
import com.reactnativenavigation.views.utils.Point;

public class SharedElementTransition extends FrameLayout {
    public ViewGroup.LayoutParams childLayoutParams;

    public SharedElementParamsParser paramsParser = new SharedElementParamsParser();
    public SharedElementTransitionParams showTransitionParams;
    public SharedElementTransitionParams hideTransitionParams;
    private View child;
    private int childLeft;
    private int childTop;
    private int childWidth = -1;
    private int childHeight = -1;
    private SpannableString spannableText;
    private SpannedString spannedText;

    public View getSharedView() {
        return child;
    }

    public SharedElementTransition(Context context) {
        super(context);
    }

    public void registerSharedElementTransition(final String key) {
        ViewUtils.runOnPreDraw(this, new Runnable() {
            @Override
            public void run() {
                ViewUtils.performOnParentScreen(SharedElementTransition.this, new Task<Screen>() {
                    @Override
                    public void run(Screen screen) {
                        screen.registerSharedElement(SharedElementTransition.this, key);
                    }
                });
            }
        });
    }

    @Override
    public void onViewAdded(final View child) {
        if (child instanceof ReactImageView && this.child == null) {
            ReactViewHacks.disableReactImageViewRemoteImageFadeInAnimation((ReactImageView) child);
        }
        this.child = child;
        if (child instanceof TextView) {
            saveTextViewSpannedText((TextView) child);
        }
        super.onViewAdded(child);
    }

    private void saveTextViewSpannedText(final TextView view) {
        ViewUtils.runOnPreDraw(view, new Runnable() {
            @Override
            public void run() {
                if (spannableText == null) {
                    spannedText = new SpannedString(view.getText());
                }
                if (spannableText == null) {
                    spannableText = new SpannableString(spannedText);
                }
            }
        });
    }

    @Keep
    public void setCurvedMotion(PathPoint xy) {
        child.setTranslationX(xy.mX);
        child.setTranslationY(xy.mY);
    }

    @Keep
    public void setTextColor(double[] color) {
        if (child instanceof TextView) {
            ViewUtils.setSpanColor(spannableText, ColorUtils.labToColor(color));
            ((TextView) child).setText(spannableText);
        }
    }

    @Keep
    public void setClipBounds(Rect clipBounds) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            child.setClipBounds(clipBounds);
        }
    }

    @Keep
    public void setMatrixTransform(float value) {
        GenericDraweeHierarchy hierarchy = ((DraweeView<GenericDraweeHierarchy>) child).getHierarchy();
        ((ScalingUtils.InterpolatingScaleType) hierarchy.getActualImageScaleType()).setValue(value);
        child.invalidate();
    }

    public void attachChildToScreen() {
        ViewUtils.performOnParentScreen(this, new Task<Screen>() {
            @Override
            public void run(Screen screen) {
                saveChildParams(child);
                Point childLocationInScreen = ViewUtils.getLocationOnScreen(child);

                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(childWidth, childHeight);
                removeView(child);
                lp.leftMargin = childLocationInScreen.x;
                lp.topMargin = childLocationInScreen.y;

                screen.addView(child, lp);
            }

            private void saveChildParams(final View child) {
                childLayoutParams = child.getLayoutParams();
                childLeft = child.getLeft();
                childTop = child.getTop();
                if (childWidth == -1) {
                    childWidth = child.getWidth();
                }
                if (childHeight == -1) {
                    childHeight = child.getHeight();
                }
            }
        });
    }

    public void attachChildToSelf() {
        ((ViewManager) child.getParent()).removeView(child);
        child.setLeft(childLeft);
        child.setTop(childTop);
        restoreTextViewSpannedText();
        addView(child, new LayoutParams(childLayoutParams));
    }

    private void restoreTextViewSpannedText() {
        if (child instanceof TextView) {
            ((TextView) child).setText(spannedText);
            spannedText = null;
            spannableText = null;
        }
    }

    public void show() {
        setVisibility(VISIBLE);
        ViewUtils.runOnPreDraw(child, new Runnable() {
            @Override
            public void run() {
                child.setAlpha(1);
            }
        });
    }

    public void hide() {
        setVisibility(INVISIBLE);
        child.setAlpha(0);
    }
}