package segmented_control.widget.custom.android.com.segmentedcontrol.utils;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.support.annotation.IntRange;
import android.view.View;

import segmented_control.widget.custom.android.com.segmentedcontrol.item_row_column.SegmentBackgroundType;
import segmented_control.widget.custom.android.com.segmentedcontrol.item_row_column.SegmentViewHolder;

/**
 * Created by Robert Apikyan on 9/8/2017.
 */

public class Utils {
    public static <T> T lazy(T nullable, T nonNull) {
        if (nullable == null) {
            nullable = nonNull;
        }
        return nullable;
    }

    /**
     * Utility method, use to define segment background type
     *
     * @param absolutePosition, Segment absolute position from {@link SegmentViewHolder#getAbsolutePosition()}
     * @param columnCount,      from {@link SegmentViewHolder#getColumnCount()}
     * @param size,             from {@link SegmentViewHolder#getCurrentSize()}
     * @return {@link SegmentBackgroundType}
     */
    @SegmentBackgroundType
    public static int defineSegmentBackground(@IntRange(from = 0) int absolutePosition, @IntRange(from = 1) int columnCount, @IntRange(from = 1) int size) {

        // if only one item
        if (size == 1) {
            return SegmentBackgroundType.SINGLE_BG;
        }

        // if one column
        if (columnCount == 1) {
            // for first
            if (absolutePosition == 0) {
                return SegmentBackgroundType.TOP_SINGLE_BG;
            }

            // for last
            if (absolutePosition == size - 1) {
                return SegmentBackgroundType.BOTTOM_SINGLE_BG;
            }
        }

        // if not one column, but one row
        if (size <= columnCount) {
            if (absolutePosition == 0) {
                return SegmentBackgroundType.TOP_LEFT_SINGLE_BG;
            }

            if (absolutePosition == size - 1) {
                return SegmentBackgroundType.TOP_RIGHT_SINGLE_BG;
            }
        }

        // if not one column and multi row
        if (absolutePosition == 0) {
            return SegmentBackgroundType.TOP_LEFT_BG;
        }

        if (absolutePosition == columnCount - 1) {
            return SegmentBackgroundType.TOP_RIGHT_BG;
        }

        int notCompletedRowItemsCount = size % columnCount;

        int completeRowsItemsCount = size - notCompletedRowItemsCount;

        if (notCompletedRowItemsCount == 1 && absolutePosition == completeRowsItemsCount) {
            return SegmentBackgroundType.BOTTOM_SINGLE_BG;
        }

        if (notCompletedRowItemsCount == 0) {
            if (absolutePosition == size - columnCount) {
                return SegmentBackgroundType.BOTTOM_LEFT_BG;
            }
            if (absolutePosition == size - 1) {
                return SegmentBackgroundType.BOTTOM_RIGHT_BG;
            }
        } else if (notCompletedRowItemsCount > 0) {
            if (absolutePosition == size - notCompletedRowItemsCount) {
                return SegmentBackgroundType.BOTTOM_LEFT_BG;
            }
            if (absolutePosition == size - 1) {
                return SegmentBackgroundType.BOTTOM_RIGHT_BG;
            }
        }

        return SegmentBackgroundType.MIDDLE_BG;
    }

    /**
     * Use to define segment corner radius
     *
     * @param absolutePosition,  Segment absolute position from {@link SegmentViewHolder#getAbsolutePosition()}
     * @param columnCount,       from {@link SegmentViewHolder#getColumnCount()}
     * @param size,              from {@link SegmentViewHolder#getCurrentSize()}
     * @param topLeftRadius,     from {@link SegmentViewHolder#getTopLeftRadius()}
     * @param topRightRadius,    from {@link SegmentViewHolder#getTopRightRadius()} ()}
     * @param bottomRightRadius, from {@link SegmentViewHolder#getBottomRightRadius()}
     * @param bottomLeftRadius,  from  {@link SegmentViewHolder#getBottomLeftRadius()}
     * @return, float[] corners radius,
     */
    public static float[] defineRadiusForPosition(@IntRange(from = 0) int absolutePosition, @IntRange(from = 1) int columnCount, @IntRange(from = 1) int size,
                                                  int topLeftRadius, int topRightRadius, int bottomRightRadius, int bottomLeftRadius) {
        @SegmentBackgroundType
        int bgType = defineSegmentBackground(absolutePosition, columnCount, size);

        switch (bgType) {

            case SegmentBackgroundType.BOTTOM_LEFT_BG:
                return createRadius(0, 0, 0, bottomLeftRadius);

            case SegmentBackgroundType.BOTTOM_RIGHT_BG:
                return createRadius(0, 0, bottomRightRadius, 0);

            case SegmentBackgroundType.BOTTOM_SINGLE_BG:
                return createRadius(0, 0, bottomRightRadius, bottomLeftRadius);

            case SegmentBackgroundType.MIDDLE_BG:
                return createRadius(0, 0, 0, 0);

            case SegmentBackgroundType.SINGLE_BG:
                return createRadius(topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius);

            case SegmentBackgroundType.TOP_LEFT_BG:
                return createRadius(topLeftRadius, 0, 0, 0);

            case SegmentBackgroundType.TOP_LEFT_SINGLE_BG:
                return createRadius(topLeftRadius, 0, 0, bottomLeftRadius);

            case SegmentBackgroundType.TOP_RIGHT_BG:
                return createRadius(0, topRightRadius, 0, 0);

            case SegmentBackgroundType.TOP_RIGHT_SINGLE_BG:
                return createRadius(0, topRightRadius, bottomRightRadius, 0);

            case SegmentBackgroundType.TOP_SINGLE_BG:
                return createRadius(topLeftRadius, topRightRadius, 0, 0);

            default:
                return createRadius(0, 0, 0, 0);
        }
    }

    public static float[] createRadius(float topLeft, float topRight, float bottomRight, float bottomLeft) {
        return new float[]{topLeft, topLeft, topRight, topRight, bottomRight, bottomRight, bottomLeft, bottomLeft};
    }

    /**
     * @param strokeWidth, stroke width
     * @param strokeColor, stroke color
     * @param argb,        background color
     * @param radii,       use {@link #defineRadiusForPosition(int, int, int, int, int, int, int)} method to define radii
     * @return background drawable
     */
    public static Drawable getBackground(int strokeWidth, int strokeColor, int argb, float[] radii) {
        GradientDrawable drawable = new GradientDrawable();
        drawable.setShape(GradientDrawable.RECTANGLE);
        drawable.setStroke(strokeWidth, strokeColor);
        drawable.setCornerRadii(radii);
        drawable.setColor(argb);
        return drawable;
    }

    public static ValueAnimator createBackgroundAnimation(int argbStart, int argbEnd) {
        return ValueAnimator.ofObject(ArgbEvaluator.getInstance(), argbStart, argbEnd);
    }

    public static boolean isInBounds(float touchX, float touchY, float viewX, float viewY, float viewW, float viewH) {
        return touchX >= viewX && touchX <= viewX + viewW && // in x bounds
                touchY >= viewY && touchY <= viewY + viewH;
    }
}