package com.wasu.frescoimagefetchermodule;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Animatable;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.widget.ImageView;

import com.facebook.cache.disk.DiskCacheConfig;
import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.internal.Supplier;
import com.facebook.common.references.CloseableReference;
import com.facebook.common.util.ByteConstants;
import com.facebook.datasource.BaseDataSubscriber;
import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.backends.pipeline.PipelineDraweeController;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.controller.ControllerListener;
import com.facebook.drawee.generic.RoundingParams;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.imagepipeline.cache.MemoryCacheParams;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.image.ImageInfo;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.wasu.module.log.WLog;


/**
 * Created by jeepc on 2016/9/26.
 * fresco图片加载模块，需要将图片控件替换为SimpleDraweeView
 */

public class FrescoImageFetcherModule extends IModule implements FrescoImageFetcherInterface {


    private static final String TAG = "FrescoImageFetcherModule";

    private static int MAX_MEM = 40 * ByteConstants.MB;
    private static int MAX_DISK = 100 * ByteConstants.MB;


    /**
     * 全局配置
     */
    private ImagePipelineConfig config;


    public ImagePipelineConfig getImagePipelineConfig() {
        return config;
    }

    /**
     * single instance
     */
    private volatile static FrescoImageFetcherModule g_instance;

    /**
     * 获取实体类单例
     *
     * @return ImageFetcherModule单例
     */
    public static FrescoImageFetcherModule getInstance() {
        if (g_instance == null) {
            synchronized (Object.class) {
                if (g_instance == null) {
                    g_instance = new FrescoImageFetcherModule();
                }
            }
        }
        return g_instance;
    }

    /**
     * 初始化
     *
     * @param c 上下文环境
     */
    public void init(Context c) {
        if (isInited()) {
            return;
        }
        setContext(c);


        DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(c)
                .setMaxCacheSize(MAX_DISK)
                .build();//磁盘缓存


        final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams(
                MAX_MEM,// 内存缓存中总图片的最大大小,以字节为单位。
                Integer.MAX_VALUE,// 内存缓存中图片的最大数量。
                MAX_MEM,// 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。
                Integer.MAX_VALUE,// 内存缓存中准备清除的总图片的最大数量。
                Integer.MAX_VALUE);// 内存缓存中单个图片的最大大小。

        Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() {
            @Override
            public MemoryCacheParams get() {
                return bitmapCacheParams;
            }
        };


        config = ImagePipelineConfig.newBuilder(c)
                .setBitmapsConfig(Bitmap.Config.RGB_565)//rgb设置
                .setDownsampleEnabled(true)
                .setResizeAndRotateEnabledForNetwork(true)
                .setMainDiskCacheConfig(diskCacheConfig)
                .setBitmapMemoryCacheParamsSupplier(mSupplierMemoryCacheParams)
                .build();


        init();

        setInited(true);
    }

    protected FrescoImageFetcherModule() {

    }

    /**
     * 设置圆形图片
     *
     * @param imageView 显示的控件
     * @param imgUrl    图片链接
     */
    public static void setRouteDisplayImager(ImageView imageView, String imgUrl) {
        try {
            if (imgUrl == null) {
                WLog.e(TAG, "url is null!");
                return;
            }
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;
            simpleDraweeView.getHierarchy().setRoundingParams(new RoundingParams().setRoundAsCircle(true));
            simpleDraweeView.setImageURI(Uri.parse(imgUrl));
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }

    }

    /**
     * 初始化
     */
    private synchronized void init() {
        Fresco.initialize(getContext(), config);
    }


    /**
     * 普通加载
     *
     * @param imgUrl
     * @param imageView
     */
    @Override
    public void attachImage(String imgUrl, ImageView imageView) {
        try {
            if (imgUrl == null) {
                WLog.e(TAG, "url is null!");
                return;
            }
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;

            simpleDraweeView.setImageURI(Uri.parse(imgUrl));
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    /**
     * 圆角
     *
     * @param imgUrl
     * @param imageView
     * @param radius    圆角半径
     */
    @Override
    public void attachImage(String imgUrl, ImageView imageView, int radius) {
        try {
            if (imgUrl == null) {
                WLog.e(TAG, "url is null!");
                return;
            }
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;
            RoundingParams roundingParams = RoundingParams.fromCornersRadius(radius);
            simpleDraweeView.getHierarchy().setRoundingParams(roundingParams);
            simpleDraweeView.setImageURI(Uri.parse(imgUrl));
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    public void attachImageResize(@NonNull String imgUrl, ImageView imageView, int width, int height) {
        try {
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;

            ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(imgUrl))
                    .setResizeOptions(new ResizeOptions(width, height))
                    .build();
            PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                    .setOldController(simpleDraweeView.getController())
                    .setImageRequest(request)
                    .setAutoPlayAnimations(true)//gif图自动播放
                    .build();
            simpleDraweeView.setController(controller);
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    /**
     * @param imgUrl
     * @param imageView
     * @param listener
     */
    @Override
    public void attachImage(final String imgUrl, ImageView imageView, final ImageFetchListener listener) {
        try {
            if (imgUrl == null) {
                WLog.e(TAG, "url is null!");
                return;
            }
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;
            final ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
                @Override
                public void onFailure(String id, Throwable throwable) {
                    if (listener != null) {
                        listener.onFetchFailed(imgUrl,throwable);
                    }
                }

                @Override
                public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
                    if(listener!=null){
                        listener.onFetchCompleted(imgUrl,null);
                    }
                }
            };
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setControllerListener(controllerListener)
                    .setUri(Uri.parse(imgUrl))
                    .build();
            simpleDraweeView.setController(controller);
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    @Override
    public void attachImageAlpha(String imgUrl, ImageView imageView, ImageFetchListener listener) {
        // TODO: 2016/11/22
    }

    /**
     * 圆角、渐进
     *
     * @param imgUrl
     * @param imageView
     * @param radius
     * @param duration
     */

    @Override
    public void attachImageAlpha(String imgUrl, ImageView imageView, int radius, int duration) {
        try {
            if (imgUrl == null) {
                WLog.e(TAG, "url is null!");
                return;
            }
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;
            RoundingParams roundingParams = RoundingParams.fromCornersRadius(radius);
            simpleDraweeView.getHierarchy().setRoundingParams(roundingParams);
            simpleDraweeView.getHierarchy().setFadeDuration(duration);
            simpleDraweeView.setImageURI(Uri.parse(imgUrl));
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    /**
     * 渐进
     *
     * @param imgUrl
     * @param imageView
     * @param duration
     */

    @Override
    public void attachImageAlpha(String imgUrl, ImageView imageView, int duration) {
        try {
            if (imgUrl == null) {
                WLog.e(TAG, "url is null!");
                return;
            }
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;
            simpleDraweeView.getHierarchy().setFadeDuration(duration);
            simpleDraweeView.setImageURI(Uri.parse(imgUrl));
        } catch (ClassCastException e) {
            WLog.e(TAG, imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    @Override
    public Bitmap getImage(String imgUrl) {
        // TODO: 2016/11/22
        return null;
    }

    @Override
    public Bitmap getImage(String imgUrl, int targetImageWidth, int targetImageHeight) {
        // TODO: 2016/11/22
        return null;
    }

    /**
     * 使用此方法需手动释放资源
     *
     * @param imgUrl
     * @param listener
     */
    @Override
    public void loadImage(final String imgUrl, final ImageFetchListener listener) {
        if (imgUrl == null) {
            WLog.e(TAG, "url is null!");
            return;
        }
        ImageRequest imageRequest = ImageRequestBuilder
                .newBuilderWithSource(Uri.parse(imgUrl))
                .setProgressiveRenderingEnabled(true)
                .build();
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, getContext());
        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {

            @Override
            protected void onNewResultImpl(DataSource dataSource) {
                if (listener != null) {
                    listener.onFetchCompleted(imgUrl, dataSource);
                }
            }

            @Override
            protected void onFailureImpl(DataSource dataSource) {
                if (listener != null) {
                    listener.onFetchFailed(imgUrl, dataSource.getFailureCause());
                }
            }
        }, UiThreadImmediateExecutorService.getInstance());

    }

    @Override
    public void cancelTask(ImageView imageView) {
        try {
            SimpleDraweeView simpleDraweeView = (SimpleDraweeView) imageView;
            // TODO: 2016/11/22
        } catch (ClassCastException e) {
            throw new ClassCastException(imageView.toString()
                    + " is not a SimpleDraweeView!");
        }
    }

    @Override
    public void stopAllTask() {
        // TODO: 2016/11/22
    }

    @Override
    public void clearMemoryCache() {
        Fresco.getImagePipeline().clearMemoryCaches();
    }

    @Override
    public void clearDiskCache() {
        Fresco.getImagePipeline().clearDiskCaches();
    }

    @Override
    public void setThreadPoolSize(int size) {
        // TODO: 2016/11/22
    }

    @Override
    public void setDisplayer() {
        // TODO: 2016/11/22
    }

}
