package com.audio.record.screen.test.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class AspectRatioCropView extends View {

    private RectF cropRect = new RectF();
    private RectF lastRect = new RectF();
    private RectF videoBounds = null;

    private Paint borderPaint;
    private Paint shadePaint;
    private float aspectRatio = 4f / 5f;
    private int minSize = 100;

    private boolean isDragging = false;
    private float lastTouchX, lastTouchY;
    private int dragHandle = 0;

    public AspectRatioCropView(Context context) {
        super(context);
        init();
    }

    public AspectRatioCropView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        borderPaint = new Paint();
        borderPaint.setColor(Color.WHITE);
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setStrokeWidth(4f);

        shadePaint = new Paint();
        shadePaint.setColor(0x33000000);
    }

    public void setVideoDisplayBounds(RectF bounds) {
        this.videoBounds = bounds;
        updateCropRect(bounds.centerX(), bounds.centerY(),
                Math.min(bounds.width(), bounds.height()) * 0.5f);
    }

    private void updateCropRect(float centerX, float centerY, float size) {
        float width, height;
        if (aspectRatio >= 1) {
            width = size;
            height = width / aspectRatio;
        } else {
            height = size;
            width = height * aspectRatio;
        }

        cropRect.left = centerX - width / 2;
        cropRect.top = centerY - height / 2;
        cropRect.right = centerX + width / 2;
        cropRect.bottom = centerY + height / 2;

        enforceBounds();
        invalidate();
    }

//    private void enforceBounds() {
//        if (videoBounds == null) return;
//
//        float dx = 0, dy = 0;
//
//        if (cropRect.left < videoBounds.left) dx = videoBounds.left - cropRect.left;
//        if (cropRect.top < videoBounds.top) dy = videoBounds.top - cropRect.top;
//        if (cropRect.right > videoBounds.right) dx = videoBounds.right - cropRect.right;
//        if (cropRect.bottom > videoBounds.bottom) dy = videoBounds.bottom - cropRect.bottom;
//
//        cropRect.offset(dx, dy);
//    }

    private void enforceBounds() {
        if (videoBounds == null) return;

        float dx = 0, dy = 0;

        // 缩小裁剪框使其适应边界
        if (cropRect.width() > videoBounds.width()) {
            float newWidth = videoBounds.width();
            float newHeight = newWidth / aspectRatio;
            cropRect.left = videoBounds.left;
            cropRect.right = videoBounds.right;
            cropRect.top = (videoBounds.top + videoBounds.bottom - newHeight) / 2;
            cropRect.bottom = cropRect.top + newHeight;
        } else if (cropRect.height() > videoBounds.height()) {
            float newHeight = videoBounds.height();
            float newWidth = newHeight * aspectRatio;
            cropRect.top = videoBounds.top;
            cropRect.bottom = videoBounds.bottom;
            cropRect.left = (videoBounds.left + videoBounds.right - newWidth) / 2;
            cropRect.right = cropRect.left + newWidth;
        }

        // 位置微调（避免轻微偏移）
        if (cropRect.left < videoBounds.left) dx = videoBounds.left - cropRect.left;
        if (cropRect.top < videoBounds.top) dy = videoBounds.top - cropRect.top;
        if (cropRect.right > videoBounds.right) dx = videoBounds.right - cropRect.right;
        if (cropRect.bottom > videoBounds.bottom) dy = videoBounds.bottom - cropRect.bottom;

        cropRect.offset(dx, dy);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int saveCount = canvas.save();

        // 阴影层
        canvas.drawRect(0, 0, getWidth(), getHeight(), shadePaint);

        // 剪裁中间区域
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            canvas.clipOutRect(cropRect);
        } else {
            canvas.clipRect(cropRect, android.graphics.Region.Op.DIFFERENCE);
        }

        canvas.drawColor(0x99000000);
        canvas.restoreToCount(saveCount);

        // 边框
        canvas.drawRect(cropRect, borderPaint);

        // 四角标记
        float cornerSize = 20f;
        canvas.drawLine(cropRect.left, cropRect.top, cropRect.left + cornerSize, cropRect.top, borderPaint);
        canvas.drawLine(cropRect.left, cropRect.top, cropRect.left, cropRect.top + cornerSize, borderPaint);

        canvas.drawLine(cropRect.right, cropRect.top, cropRect.right - cornerSize, cropRect.top, borderPaint);
        canvas.drawLine(cropRect.right, cropRect.top, cropRect.right, cropRect.top + cornerSize, borderPaint);

        canvas.drawLine(cropRect.right, cropRect.bottom, cropRect.right - cornerSize, cropRect.bottom, borderPaint);
        canvas.drawLine(cropRect.right, cropRect.bottom, cropRect.right, cropRect.bottom - cornerSize, borderPaint);

        canvas.drawLine(cropRect.left, cropRect.bottom, cropRect.left + cornerSize, cropRect.bottom, borderPaint);
        canvas.drawLine(cropRect.left, cropRect.bottom, cropRect.left, cropRect.bottom - cornerSize, borderPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (videoBounds == null) return false;

        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastRect.set(cropRect);

                if (isInCorner(x, y, cropRect.left, cropRect.top)) dragHandle = 2;
                else if (isInCorner(x, y, cropRect.right, cropRect.top)) dragHandle = 3;
                else if (isInCorner(x, y, cropRect.right, cropRect.bottom)) dragHandle = 4;
                else if (isInCorner(x, y, cropRect.left, cropRect.bottom)) dragHandle = 5;
                else if (cropRect.contains(x, y)) dragHandle = 1;
                else dragHandle = 0;

                lastTouchX = x;
                lastTouchY = y;
                isDragging = dragHandle != 0;
                return isDragging;

            case MotionEvent.ACTION_MOVE:
                if (!isDragging) return false;
                lastRect.set(cropRect);

                float dx = x - lastTouchX;
                float dy = y - lastTouchY;

                if (dragHandle == 1) {
                    cropRect.offset(dx, dy);
                    enforceBounds();
                } else {
                    float newWidth, newHeight;

                    switch (dragHandle) {
                        case 2:
                            newWidth = cropRect.width() - dx;
                            newHeight = newWidth / aspectRatio;
                            cropRect.left = cropRect.right - newWidth;
                            cropRect.top = cropRect.bottom - newHeight;
                            break;
                        case 3:
                            newWidth = cropRect.width() + dx;
                            newHeight = newWidth / aspectRatio;
                            cropRect.right = cropRect.left + newWidth;
                            cropRect.top = cropRect.bottom - newHeight;
                            break;
                        case 4:
                            newWidth = cropRect.width() + dx;
                            newHeight = newWidth / aspectRatio;
                            cropRect.right = cropRect.left + newWidth;
                            cropRect.bottom = cropRect.top + newHeight;
                            break;
                        case 5:
                            newWidth = cropRect.width() - dx;
                            newHeight = newWidth / aspectRatio;
                            cropRect.left = cropRect.right - newWidth;
                            cropRect.bottom = cropRect.top + newHeight;
                            break;
                    }

                    if (cropRect.width() < minSize || cropRect.height() < minSize) {
                        cropRect.set(lastRect);
                    }

                    enforceBounds();
                }

                lastTouchX = x;
                lastTouchY = y;
                invalidate();
                return true;

            case MotionEvent.ACTION_UP:
                isDragging = false;
                return true;
        }

        return false;
    }

    private boolean isInCorner(float x, float y, float cornerX, float cornerY) {
        float touchArea = 50f;
        return x >= cornerX - touchArea && x <= cornerX + touchArea &&
                y >= cornerY - touchArea && y <= cornerY + touchArea;
    }

    public void setAspectRatio(float ratio) {
        this.aspectRatio = ratio;
        if (videoBounds != null) {
            float centerX = cropRect.centerX();
            float centerY = cropRect.centerY();
            float size = Math.max(cropRect.width(), cropRect.height());
            updateCropRect(centerX, centerY, size);
        }
    }

    public RectF getCropRect() {
        return new RectF(cropRect);
    }


    @Nullable
    public RectF getCropRectInVideoCoords(int videoWidth, int videoHeight) {
        if (videoBounds == null) return null;

        float scaleX = videoWidth / videoBounds.width();
        float scaleY = videoHeight / videoBounds.height();

        float left = (cropRect.left - videoBounds.left) * scaleX;
        float top = (cropRect.top - videoBounds.top) * scaleY;
        float width = cropRect.width() * scaleX;
        float height = cropRect.height() * scaleY;

        return new RectF(left, top, left + width, top + height);
    }

}
