package com.remax.visualnovel.widget.glidetransformation;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.RectF;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import java.security.MessageDigest;
import jp.wasabeef.glide.transformations.BitmapTransformation;
import jp.wasabeef.glide.transformations.BuildConfig;

/**
 * Created by HJW on 2023/7/25
 */
public class CropRectTransformation extends BitmapTransformation {

    private static final int VERSION = 1;
    private static final String ID = "com.remax.visualnovel.widget.glidetransformation.CropTransformation." + VERSION;

    public enum CropXType {
        TOP,
        CENTER,
        BOTTOM
    }

    public enum CropYType {
        LEFT,
        CENTER,
        RIGHT
    }

    private int width;
    private int height;

    private final CropXType cropXType;
    private final CropYType cropYType;

    public CropRectTransformation(int width, int height) {
        this(width, height, CropXType.CENTER, CropYType.CENTER);
    }

    public CropRectTransformation(int width, int height, CropXType cropXType, CropYType cropYType) {
        this.width = width;
        this.height = height;
        this.cropXType = cropXType;
        this.cropYType = cropYType;
    }

    @Override
    protected Bitmap transform(@NonNull Context context, @NonNull BitmapPool pool,
                               @NonNull Bitmap toTransform, int outWidth, int outHeight) {

        width = width == 0 ? toTransform.getWidth() : width;
        height = height == 0 ? toTransform.getHeight() : height;

        Bitmap.Config config =
                toTransform.getConfig() != null ? toTransform.getConfig() : Bitmap.Config.ARGB_8888;
        Bitmap bitmap = pool.get(width, height, config);

        bitmap.setHasAlpha(true);

        float scaleX = (float) width / toTransform.getWidth();
        float scaleY = (float) height / toTransform.getHeight();
        float scale = Math.max(scaleX, scaleY);

        float scaledWidth = scale * toTransform.getWidth();
        float scaledHeight = scale * toTransform.getHeight();
        float left = getLeft(scaledWidth);
        float top = getTop(scaledHeight);
        RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);

        bitmap.setDensity(toTransform.getDensity());

        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(toTransform, null, targetRect, null);

        return bitmap;
    }

    private float getTop(float scaledHeight) {
        switch (cropXType) {
            case CENTER:
                return (height - scaledHeight) / 2;
            case BOTTOM:
                return height - scaledHeight;
            default:
                return 0;
        }
    }

    private float getLeft(float scaledWidth) {
        switch (cropYType) {
            case CENTER:
                return (width - scaledWidth) / 2;
            case RIGHT:
                return width - scaledWidth;
            default:
                return 0;
        }
    }


    @NonNull
    @Override
    public String toString() {
        return "CropTransformation(width=" + width + ", height=" + height + ", cropXType=" + cropXType + ", cropYType=" + cropYType + ")";
    }

    @Override
    public boolean equals(Object o) {
        return o instanceof CropRectTransformation &&
                ((CropRectTransformation) o).width == width &&
                ((CropRectTransformation) o).height == height &&
                ((CropRectTransformation) o).cropXType == cropXType &&
                ((CropRectTransformation) o).cropYType == cropYType;
    }

    @Override
    public int hashCode() {
        return ID.hashCode() + width * 100000 + height * 1000 + cropXType.ordinal() * 10 + cropYType.ordinal() * 10;
    }

    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
        messageDigest.update((ID + width + height + cropXType + cropYType).getBytes(CHARSET));
    }
}
