package com.ytpm.hydtw.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.request.RequestOptions;

import java.nio.ByteBuffer;
import java.security.MessageDigest;

public class GlideRoundedCorners {

    /**
     * 加载圆形图片
     */
    public static void loadCircleImage(Context context, String url, ImageView imageView) {
        Glide.with(context)
                .load(url)
                .apply(RequestOptions.circleCropTransform())
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(imageView);
    }

    /**
     * 加载圆角图片（全部角）
     */
    public static void loadRoundedImage(Context context, String url, ImageView imageView, int radius) {
        Glide.with(context)
                .load(url)
                .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(radius)))
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(imageView);
    }

    /**
     * 加载部分圆角图片
     */
    public static void loadRoundedImage(Context context, String url, ImageView imageView, int radius, int cornerType) {
        Glide.with(context)
                .load(url)
                .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(radius, cornerType)))
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(imageView);
    }

    /**
     * 加载带边框的圆形图片
     */
    public static void loadCircleImageWithBorder(Context context, String url, ImageView imageView, int borderWidth, int borderColor) {
        Glide.with(context)
                .load(url)
                .apply(RequestOptions.bitmapTransform(new CircleWithBorderTransformation(borderWidth, borderColor)))
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(imageView);
    }

    /**
     * 圆角转换类
     */
    public static class RoundedCornersTransformation extends BitmapTransformation {

        public static final int CORNER_ALL = 0;
        public static final int CORNER_TOP_LEFT = 1;
        public static final int CORNER_TOP_RIGHT = 1 << 1;
        public static final int CORNER_BOTTOM_LEFT = 1 << 2;
        public static final int CORNER_BOTTOM_RIGHT = 1 << 3;
        public static final int CORNER_TOP = CORNER_TOP_LEFT | CORNER_TOP_RIGHT;
        public static final int CORNER_BOTTOM = CORNER_BOTTOM_LEFT | CORNER_BOTTOM_RIGHT;
        public static final int CORNER_LEFT = CORNER_TOP_LEFT | CORNER_BOTTOM_LEFT;
        public static final int CORNER_RIGHT = CORNER_TOP_RIGHT | CORNER_BOTTOM_RIGHT;

        private static final String ID = "com.bumptech.glide.transformations.RoundedCornersTransformation";
        private static final byte[] ID_BYTES = ID.getBytes(CHARSET);

        private final int radius;
        private final int cornerType;

        public RoundedCornersTransformation(int radius) {
            this.radius = radius;
            this.cornerType = CORNER_ALL;
        }

        public RoundedCornersTransformation(int radius, int cornerType) {
            this.radius = radius;
            this.cornerType = cornerType;
        }

        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            if (toTransform == null) return null;

            Bitmap bitmap = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
            if (bitmap == null) {
                bitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
            }

            Canvas canvas = new Canvas(bitmap);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setShader(new BitmapShader(toTransform, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            drawRoundRect(canvas, paint, outWidth, outHeight, radius, cornerType);
            return bitmap;
        }

        private void drawRoundRect(Canvas canvas, Paint paint, float width, float height, float radius, int cornerType) {
            float halfRadius = radius / 2;
            RectF rect = new RectF(0, 0, width, height);

            if (cornerType == CORNER_ALL) {
                canvas.drawRoundRect(rect, halfRadius, halfRadius, paint);
            } else {
                float[] radii = new float[8];

                if ((cornerType & CORNER_TOP_LEFT) != 0) {
                    radii[0] = halfRadius; radii[1] = halfRadius;
                }

                if ((cornerType & CORNER_TOP_RIGHT) != 0) {
                    radii[2] = halfRadius; radii[3] = halfRadius;
                }

                if ((cornerType & CORNER_BOTTOM_RIGHT) != 0) {
                    radii[4] = halfRadius; radii[5] = halfRadius;
                }

                if ((cornerType & CORNER_BOTTOM_LEFT) != 0) {
                    radii[6] = halfRadius; radii[7] = halfRadius;
                }

                Path path = new Path();
                path.addRoundRect(rect, radii, Path.Direction.CW);
                canvas.drawPath(path, paint);
            }
        }

        @Override
        public void updateDiskCacheKey(MessageDigest messageDigest) {
            messageDigest.update(ID_BYTES);
            byte[] radiusData = ByteBuffer.allocate(4).putInt(radius).array();
            messageDigest.update(radiusData);
            byte[] cornerTypeData = ByteBuffer.allocate(4).putInt(cornerType).array();
            messageDigest.update(cornerTypeData);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            RoundedCornersTransformation that = (RoundedCornersTransformation) o;
            return radius == that.radius && cornerType == that.cornerType;
        }

        @Override
        public int hashCode() {
            return ID.hashCode() + radius * 1000 + cornerType * 10;
        }
    }

    /**
     * 带边框的圆形转换类
     */
    public static class CircleWithBorderTransformation extends BitmapTransformation {

        private static final String ID = "com.bumptech.glide.transformations.CircleWithBorderTransformation";
        private static final byte[] ID_BYTES = ID.getBytes(CHARSET);

        private final int borderWidth;
        private final int borderColor;

        public CircleWithBorderTransformation(int borderWidth, int borderColor) {
            this.borderWidth = borderWidth;
            this.borderColor = borderColor;
        }

        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            if (toTransform == null) return null;

            Bitmap squared = centerCrop(pool, toTransform, outWidth, outHeight);
            Bitmap result = pool.get(squared.getWidth(), squared.getHeight(), Bitmap.Config.ARGB_8888);
            if (result == null) {
                result = Bitmap.createBitmap(squared.getWidth(), squared.getHeight(), Bitmap.Config.ARGB_8888);
            }

            Canvas canvas = new Canvas(result);
            Paint paint = new Paint();
            paint.setShader(new BitmapShader(squared, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            paint.setAntiAlias(true);

            float radius = squared.getWidth() / 2f;
            canvas.drawCircle(radius, radius, radius - borderWidth / 2f, paint);

            // 绘制边框
            Paint borderPaint = new Paint();
            borderPaint.setColor(borderColor);
            borderPaint.setStyle(Paint.Style.STROKE);
            borderPaint.setStrokeWidth(borderWidth);
            borderPaint.setAntiAlias(true);
            canvas.drawCircle(radius, radius, radius - borderWidth / 2f, borderPaint);

            return result;
        }

        private Bitmap centerCrop(BitmapPool pool, Bitmap source, int width, int height) {
            if (source.getWidth() == width && source.getHeight() == height) {
                return source;
            }

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

            float scaledWidth = scale * source.getWidth();
            float scaledHeight = scale * source.getHeight();

            float left = (width - scaledWidth) / 2f;
            float top = (height - scaledHeight) / 2f;

            RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);

            Bitmap.Config config = source.getConfig() != null ? source.getConfig() : Bitmap.Config.ARGB_8888;
            Bitmap result = pool.get(width, height, config);
            if (result == null) {
                result = Bitmap.createBitmap(width, height, config);
            }

            Canvas canvas = new Canvas(result);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            canvas.drawBitmap(source, null, targetRect, paint);

            return result;
        }

        @Override
        public void updateDiskCacheKey(MessageDigest messageDigest) {
            messageDigest.update(ID_BYTES);
            byte[] borderWidthData = ByteBuffer.allocate(4).putInt(borderWidth).array();
            messageDigest.update(borderWidthData);
            byte[] borderColorData = ByteBuffer.allocate(4).putInt(borderColor).array();
            messageDigest.update(borderColorData);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            CircleWithBorderTransformation that = (CircleWithBorderTransformation) o;
            return borderWidth == that.borderWidth && borderColor == that.borderColor;
        }

        @Override
        public int hashCode() {
            return ID.hashCode() + borderWidth * 1000 + borderColor * 10;
        }
    }
}
