package com.datarecovery.master.utils.bindingadapters;

import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.widget.ImageView;

import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.databinding.BindingAdapter;
import androidx.vectordrawable.graphics.drawable.Animatable2Compat;

import com.atmob.common.text.TextUtil;
import com.atmob.common.ui.SizeUtil;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.signature.ObjectKey;

public class ImageViewBindingAdapter {


    @BindingAdapter("imageRes")
    public static void setImageResource(ImageView imageView, @DrawableRes int imageRes) {
        imageView.setImageResource(imageRes);
    }

    @BindingAdapter("imageDraw")
    public static void setImageResource(ImageView imageView, Drawable drawable) {
        imageView.setImageDrawable(drawable);
    }

    @BindingAdapter({"imageRes", "radius"})
    public static void setImageResource(ImageView imageView, @DrawableRes int imageRes, int radius) {
        if (imageRes == 0) {
            imageView.setImageResource(0);
            return;
        }
        int radiusPx = (int) SizeUtil.dp2px(radius);
        Glide.with(imageView)
                .load(imageRes)
                .signature(new ObjectKey(System.currentTimeMillis()))
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .apply(new RequestOptions().transform(new RoundedCorners(radiusPx)))
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUrl", "imageThumbUrl"}, requireAll = false)
    public static void setImageUrl(ImageView imageView, String imageUrl, String imageThumbUrl) {
        imageUrl = TextUtils.isEmpty(imageUrl) ? imageThumbUrl : imageUrl;
        if (!TextUtil.isUrl(imageUrl)) {
            return;
        }
        RequestBuilder<Drawable> requestBuilder = Glide.with(imageView)
                .load(imageUrl);
        if (!TextUtils.isEmpty(imageThumbUrl)) {
            requestBuilder = requestBuilder.thumbnail(Glide.with(imageView).load(imageThumbUrl));
        }
        requestBuilder.into(imageView);
    }

    @BindingAdapter(value = {"imageUrl", "radius"})
    public static void setImageUrl(ImageView imageView, String imageUrl, int radius) {
        if (!TextUtil.isUrl(imageUrl)) {
            return;
        }
        int radiusPx = (int) SizeUtil.dp2px(radius);
        RequestOptions options = new RequestOptions();
        if (imageView.getScaleType() == ImageView.ScaleType.CENTER_CROP) {
            options = options.transform(new CenterCrop(), new RoundedCorners(radiusPx));
        } else {
            options = options.transform(new RoundedCorners(radiusPx));
        }
        Glide.with(imageView)
                .load(imageUrl)
                .apply(options)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUrl", "placeholder", "error", "radius"})
    public static void setImageUrl(ImageView imageView, String imageUrl, Drawable placeholder, Drawable error, int radius) {
        int radiusPx = (int) SizeUtil.dp2px(radius);
        RequestOptions options = new RequestOptions();
        if (imageView.getScaleType() == ImageView.ScaleType.CENTER_CROP) {
            options = options.transform(new CenterCrop(), new RoundedCorners(radiusPx));
        } else {
            options = options.transform(new RoundedCorners(radiusPx));
        }
        Glide.with(imageView)
                .load(imageUrl)
                .apply(options)
                .placeholder(placeholder)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .thumbnail(Glide.with(imageView)
                        .load(error)
                        .apply(options))
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUrl", "placeholder", "error"})
    public static void setImageUrl(ImageView imageView, String imageUrl, Drawable placeholder, Drawable error) {
        Glide.with(imageView)
                .load(imageUrl)
                .placeholder(placeholder)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .error(error)
                .into(imageView);
    }

    @BindingAdapter(value = {"android:src", "radius"})
    public static void setImageUrl(ImageView imageView, Drawable drawable, int radius) {
        if (drawable == null) {
            imageView.setImageDrawable(null);
            return;
        }
        int radiusPx = (int) SizeUtil.dp2px(radius);
        RequestOptions options = new RequestOptions();
        if (imageView.getScaleType() == ImageView.ScaleType.CENTER_CROP) {
            options = options.transform(new CenterCrop(), new RoundedCorners(radiusPx));
        } else {
            options = options.transform(new RoundedCorners(radiusPx));
        }
        Glide.with(imageView)
                .load(drawable)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .apply(options)
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUrl", "circle"})
    public static void setImageUrl(ImageView imageView, String imageUrl, boolean circle) {
        if (!TextUtil.isUrl(imageUrl)) {
            return;
        }
        if (circle) {
            Glide.with(imageView)
                    .load(imageUrl)
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .apply(new RequestOptions().transform(new CircleCrop()))
                    .into(imageView);
        } else {
            setImageUrl(imageView, imageUrl, null);
        }
    }

    @BindingAdapter(value = {"imageUri", "circle"})
    public static void setImageUri(ImageView imageView, String imageUri, boolean circle) {
        if (TextUtils.isEmpty(imageUri)) {
            return;
        }
        if (circle) {
            Glide.with(imageView)
                    .load(imageUri)
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .apply(new RequestOptions().transform(new CircleCrop()))
                    .into(imageView);
        } else {
            setImageUri(imageView, imageUri);
        }
    }

    @BindingAdapter(value = {"imageUri"})
    public static void setImageUri(ImageView imageView, String uri) {
        if (TextUtils.isEmpty(uri)) {
            return;
        }
        setImageUri(imageView, Uri.parse(uri));
    }

    @BindingAdapter(value = {"imageUri", "radius"})
    public static void setImageUri(ImageView imageView, String uri, int radius) {
        if (TextUtils.isEmpty(uri)) {
            return;
        }
        setImageUri(imageView, Uri.parse(uri), radius);
    }

    @BindingAdapter(value = {"imageUri"})
    public static void setImageUri(ImageView imageView, Uri uri) {
        if (uri == null) {
            return;
        }
        Glide.with(imageView)
                .load(uri)
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUri", "radius"})
    public static void setImageUri(ImageView imageView, Uri uri, int radius) {
        if (uri == null) {
            return;
        }
        int radiusPx = (int) SizeUtil.dp2px(radius);
        RequestOptions options = new RequestOptions();
        if (imageView.getScaleType() == ImageView.ScaleType.CENTER_CROP) {
            options = options.transform(new CenterCrop(), new RoundedCorners(radiusPx));
        } else {
            options = options.transform(new RoundedCorners(radiusPx));
        }
        Glide.with(imageView)
                .load(uri)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .apply(options)
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUri", "placeholder", "radius"})
    public static void setImageUri(ImageView imageView, Uri uri, Drawable placeholder, int radius) {
        if (uri == null) {
            return;
        }
        int radiusPx = (int) SizeUtil.dp2px(radius);
        RequestOptions options = new RequestOptions();
        if (imageView.getScaleType() == ImageView.ScaleType.CENTER_CROP) {
            options = options.transform(new CenterCrop(), new RoundedCorners(radiusPx));
        } else {
            options = options.transform(new RoundedCorners(radiusPx));
        }
        Glide.with(imageView)
                .load(uri)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .apply(options)
                .placeholder(placeholder)
                .into(imageView);
    }

    @BindingAdapter(value = {"imageUrl", "gifInterval"})
    public static void setGifUrl(ImageView imageView, String imageUrl, long interval) {
        Glide.with(imageView)
                .load(imageUrl)
                .listener(new RequestListener<Drawable>() {
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                        GifDrawable gifDrawable = resource instanceof GifDrawable ? ((GifDrawable) resource) : null;
                        if (gifDrawable == null) {
                            return false;
                        }
                        gifDrawable.setLoopCount(1);
                        gifDrawable.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
                            @Override
                            public void onAnimationStart(Drawable drawable) {
                                super.onAnimationStart(drawable);
                            }

                            @Override
                            public void onAnimationEnd(Drawable drawable) {
                                super.onAnimationEnd(drawable);
                                imageView.postDelayed(gifDrawable::start, interval);
                            }
                        });
                        return false;
                    }
                })
                .into(imageView);
    }

    /**
     * {@link ImageView#getDrawable()}不为空时才生效
     */
    @BindingAdapter(value = {"tint"})
    public static void setTint(ImageView imageView, @ColorInt int tint) {
        imageView.setImageTintList(ColorStateList.valueOf(tint));
    }
}