package com.termux.shared.view;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;


public class ViewUtils {

    /**
     * Get the {@link Rect} of a {@link View} and the  {@link Rect} of the window inside which it
     * exists.
     * <p>
     <a href="  * https://stackoverflow.com/a/51078418/1468">...</a>6958
     *
     * @param view The {@link View} inside the window whose {@link Rect} to get.
     * @param statusBarHeight The status bar height received by {@link View.OnApplyWindowInsetsListener}.
     * @return Returns {@link Rect[]} if view is visible where Rect[0] will contain window
     * {@link Rect} and Rect[1] will contain view {@link Rect}. This will be {@code null}
     * if view is not visible.
     */
    @Nullable
    public static Rect[] getWindowAndViewRects(View view, int statusBarHeight) {
        if (view == null || !view.isShown())
            return null;

        // windowRect - will hold available area where content remain visible to users
        // Takes into account screen decorations (e.g. statusbar)
        Rect windowRect = new Rect();
        view.getWindowVisibleDisplayFrame(windowRect);

        // If there is actionbar, get his height
        int actionBarHeight = 0;
        boolean isInMultiWindowMode = false;
        Context context = view.getContext();
        if (context instanceof AppCompatActivity) {
            ActionBar actionBar = ((AppCompatActivity) context).getSupportActionBar();
            if (actionBar != null) actionBarHeight = actionBar.getHeight();
            isInMultiWindowMode = ((AppCompatActivity) context).isInMultiWindowMode();
        } else if (context instanceof Activity) {
            android.app.ActionBar actionBar = ((Activity) context).getActionBar();
            if (actionBar != null) actionBarHeight = actionBar.getHeight();
            isInMultiWindowMode = ((Activity) context).isInMultiWindowMode();
        }

        int displayOrientation = getDisplayOrientation(context);

        // windowAvailableRect - takes into account actionbar and statusbar height
        Rect windowAvailableRect;
        windowAvailableRect = new Rect(windowRect.left, windowRect.top + actionBarHeight, windowRect.right, windowRect.bottom);

        // viewRect - holds position of the view in window
        // (methods as getGlobalVisibleRect, getHitRect, getDrawingRect can return different result,
        // when partialy visible)
        Rect viewRect;
        final int[] viewsLocationInWindow = new int[2];
        view.getLocationInWindow(viewsLocationInWindow);
        int viewLeft = viewsLocationInWindow[0];
        int viewTop = viewsLocationInWindow[1];

        if (isInMultiWindowMode) {
            if (displayOrientation == Configuration.ORIENTATION_PORTRAIT) {
                // The windowRect.top of the window at the of split screen mode should start right
                // below the status bar
                if (statusBarHeight != windowRect.top) {
                    viewTop += windowRect.top;
                }
            } else if (displayOrientation == Configuration.ORIENTATION_LANDSCAPE) {
                // If window is on the right in landscape mode of split screen, the viewLeft actually
                // starts at windowRect.left instead of 0 returned by getLocationInWindow
                viewLeft += windowRect.left;
            }
        }

        int viewRight = viewLeft + view.getWidth();
        int viewBottom = viewTop + view.getHeight();
        viewRect = new Rect(viewLeft, viewTop, viewRight, viewBottom);

        if (displayOrientation == Configuration.ORIENTATION_LANDSCAPE && viewRight > windowAvailableRect.right) {
            windowAvailableRect.right = viewRight;
        }

        return new Rect[]{windowAvailableRect, viewRect};
    }

    /**
     * Check if {@link Rect} r2 is above r2. An empty rectangle never contains another rectangle.
     *
     * @param r1 The base rectangle.
     * @param r2 The rectangle being tested that should be above.
     * @return Returns {@code true} if r2 is above r1.
     */
    public static boolean isRectAbove(@NonNull Rect r1, @NonNull Rect r2) {
        // check for empty first
        return r1.left < r1.right && r1.top < r1.bottom
            // now check if above
            && r1.left <= r2.left && r1.bottom >= r2.bottom;
    }

    /**
     * Get device orientation.
     * <p>
     * Relat<a href="ed:">https://stackoverflow.com/a/29392593/1468</a>6958
     *
     * @param context The {@link Context} to check with.
     * @return {@link Configuration#ORIENTATION_PORTRAIT} or {@link Configuration#ORIENTATION_LANDSCAPE}.
     */
    public static int getDisplayOrientation(@NonNull Context context) {
        Configuration config = context.getResources().getConfiguration();
        return config.orientation;
    }

/*
    public static int getDisplayOrientation(@NonNull Context context) {
        Point size = getDisplaySize(context, false);
        return (size.x < size.y) ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
    }

    /**
     * Get device display size.
     *
     * @param context The {@link Context} to check with. It must be {@link Activity} context, otherwise
     *                android will throw:
     *                `java.lang.IllegalArgumentException: Used non-visual Context to obtain an instance of WindowManager. Please use an Activity or a ContextWrapper around one instead.`
     * @param activitySize The set to {@link true}, then size returned will be that of the activity
     *                     and can be smaller than physical display size in multi-window mode.
     * @return Returns the display size as {@link Point}.
     *//*
    public static Point getDisplaySize( @NonNull Context context, boolean activitySize) {
        // android.view.WindowManager.getDefaultDisplay() and Display.getSize() are deprecated in
        // API 30 and give wrong values in API 30 for activitySize=false in multi-window
        androidx.window.WindowManager windowManager = new androidx.window.WindowManager(context);
        androidx.window.WindowMetrics windowMetrics;
        if (activitySize)
            windowMetrics = windowManager.getCurrentWindowMetrics();
        else
            windowMetrics = windowManager.getMaximumWindowMetrics();
        return new Point(windowMetrics.getBounds().width(), windowMetrics.getBounds().height());
    }
*/

    /** Convert value in device independent pixels (dp) to pixels (px) units. */
    public static float dpToPx(Context context, float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    public static void setLayoutMarginsInDp(@NonNull View view, int left, int top, int right, int bottom) {
        Context context = view.getContext();
        setLayoutMarginsInPixels(view, (int) dpToPx(context, left), (int) dpToPx(context, top),
            (int) dpToPx(context, right), (int) dpToPx(context, bottom));
    }

    public static void setLayoutMarginsInPixels(@NonNull View view, int left, int top, int right, int bottom) {
        if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
            params.setMargins(left, top, right, bottom);
            view.setLayoutParams(params);
        }
    }

}
