/*
 * Copyright (C) 2016 J. Oliveira
 *
 *  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.alexive.graphicalutils.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewPropertyAnimator;

/**
 * Transforms plenty of methods (that usually require chiecking the sdk version, etc)
 * to a single line method call.
 */
public class ViewUtils {

    /**
     * Set the background to a given view, or remove it.
     * @param view The given view.
     * @param drawable The Drawable to be set as the background, or null to remove
     *                 the view's background.
     * @see View#setBackground(Drawable)
     */
    public static void setBackgroundDrawable(View view, Drawable drawable){
        if (Build.VERSION.SDK_INT >= 16)
            view.setBackground(drawable);
        else
            view.setBackgroundDrawable(drawable);
    }

    /**
     * Sets the view visibility as {@link View#GONE} with an animation.
     * @param view The view to animate/set as GONE.
     */
    public static void animateSetViewVisibilityGone(final View view){
        if (view.getVisibility() == View.GONE)
            return;
        if (Build.VERSION.SDK_INT < 12)
            view.setVisibility(View.GONE);
        else {
            ViewPropertyAnimator animator = view.animate();
//      animator.cancel(); //Only on API 14 cuz of this!
            animator.setListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @SuppressLint("NewApi")
                @Override
                public void onAnimationEnd(Animator animation) {
                    view.setVisibility(View.GONE);
                    view.setScaleX(0);
                    view.setScaleY(0);
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    onAnimationEnd(animation);
                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            animator.scaleX(0).scaleY(0);
        }
    }

    /**
     * Sets the view's visibility as {@link View#VISIBLE} with an animation.
     * @param view The view to animate and set visible.
     */
    public static void animateSetViewVisibilityVisible(final View view){
        if (view.getVisibility() == View.VISIBLE)
            return;
        if (Build.VERSION.SDK_INT < 12){
            view.setVisibility(View.VISIBLE);
        }else {
            ViewPropertyAnimator animator = view.animate();
//      animator.cancel(); //Only on API 14 cuz of this!
            animator.setListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    view.setVisibility(View.VISIBLE);
                    //The view is hidden if animateSetViewVisibilityGone has
                    //been called before
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    onAnimationCancel(animation);
                }

                @SuppressLint("NewApi")
                @Override
                public void onAnimationCancel(Animator animation) {
                    view.setVisibility(View.VISIBLE);
                    view.setScaleX(1);
                    view.setScaleY(1);
                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            animator.scaleX(1).scaleY(1);
        }
    }

    public static void createCircularReveal(View view, int cx, int cy, int radius){
        if (Build.VERSION.SDK_INT < 21){
            animateSetViewVisibilityVisible(view);
            return;
        }else {
            view.setVisibility(View.VISIBLE);
            //Clear traces from animateSetViewVisibility*
            if (Build.VERSION.SDK_INT >= 12) {
                view.setScaleY(1);
                view.setScaleX(1);
            }
            // get the center for the clipping circle

// get the final radius for the clipping circle

            Log.e("ViewUtils", "finalRadius = " + radius);

// create the animator for this view (the start radius is zero)
            try {

                Animator anim =
                        ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, radius);
// make the view visible and start the animation
                anim.start();
            }catch (IllegalStateException ex){
                ex.printStackTrace();
                view.setVisibility(View.VISIBLE);
            }
        }
    }

    public static void createCircularReveal(View view){
        createCircularReveal(view, (view.getLeft() + view.getRight()) / 2,
                (view.getTop() + view.getBottom()) / 2,
                Math.max(view.getWidth(), view.getHeight()));
    }

    public static void createCircularRevealInverse(final View view,
                                                   int cx,
                                                   int cy,
                                                   int initialRadius,
                                                   final boolean setAsGone){
        if (Build.VERSION.SDK_INT < 21){
            if (setAsGone)
                animateSetViewVisibilityGone(view);
            else
                view.setVisibility(View.INVISIBLE);
        }else{
            view.setVisibility(View.VISIBLE);
            if (Build.VERSION.SDK_INT >= 12) {
                view.setScaleY(1);
                view.setScaleX(1);
            }

            try {
// create the animation (the final radius is zero)
                Animator anim =
                        ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, 0);

// make the view invisible when the animation is done
                anim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        view.setVisibility(setAsGone ? View.GONE : View.INVISIBLE);
                    }
                });

// start the animation
                anim.start();
            }catch (IllegalStateException ex) {
                ex.printStackTrace();
                view.setVisibility(setAsGone ? View.GONE : View.INVISIBLE);
            }
        }
    }

    public static void createCircularRevealInverse(final View view, final boolean setAsGone){
        createCircularRevealInverse(view,
                (view.getLeft() + view.getRight()) / 2,
                (view.getTop() + view.getBottom()) / 2,
                view.getWidth(),
                setAsGone);

    }

    public static int convertDPtoPixels(Context c, int dp){
        float scale = c.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }


}