package com.cv4j.rxjava;

import android.graphics.Bitmap;
import android.util.Log;
import android.widget.ImageView;

import com.cv4j.core.datamodel.CV4JImage;
import com.cv4j.core.datamodel.ImageProcessor;
import com.cv4j.core.filters.CommonFilter;

import org.reactivestreams.Publisher;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by Tony Shen on 2017/3/14.
 */

public class RxImageData {

    CV4JImage image;
    Flowable flowable;
    MemCache memCache;
    boolean useCache = true;

    ImageView imageView;
    List<CommonFilter> filters;
    WrappedCV4JImage wrappedCV4JImage;

    private RxImageData(Bitmap bitmap) {

        this.image = new CV4JImage(bitmap);
        filters = new ArrayList<>();
        memCache = MemCache.getInstance();

        wrappedCV4JImage = new WrappedCV4JImage(image,filters);
        flowable = Flowable.just(wrappedCV4JImage);
    }

    private RxImageData(CV4JImage image) {

        this.image = image;
        filters = new ArrayList<>();
        memCache = MemCache.getInstance();

        wrappedCV4JImage = new WrappedCV4JImage(image,filters);
        flowable = Flowable.just(wrappedCV4JImage);
    }

    public static RxImageData bitmap(Bitmap bitmap) {

        return new RxImageData(bitmap);
    }

    public static RxImageData image(CV4JImage image) {

        return new RxImageData(image);
    }

    /**
     * 使用滤镜
     * @param filter
     * @return
     */
    public RxImageData addFilter(final CommonFilter filter) {

        if (filter==null) {

            Log.e("RxImageData","filter is null");
            return this;
        }

        filters.add(filter);
        return this;
    }

    /**
     * 判断是否使用缓存，默认情况使用缓存。
     * @param useCache
     * @return
     */
    public RxImageData isUseCache(boolean useCache) {

        this.useCache = useCache;
        return this;
    }

    /**
     * RxImageData.bitmap(bitmap).addFilter(new ColorFilter()).into(view);
     * @param imageview
     */
    public void into(final ImageView imageview) {

        this.imageView = imageview;
        render();
    }

    private void render() {

        if (imageView == null) {
            return;
        }

        if (filters.size()==0) {
            this.flowable.compose(RxImageData.toMain()).subscribe(new Consumer<WrappedCV4JImage>() {
                @Override
                public void accept(@NonNull WrappedCV4JImage wrapped) throws Exception {
                    imageView.setImageBitmap(wrapped.image.toBitmap());
                }
            });
        } else if (filters.size() == 1) {
            this.flowable
                    .map(new Function<WrappedCV4JImage,ImageProcessor>() {

                @Override
                public ImageProcessor apply(@NonNull WrappedCV4JImage wrap) throws
                        Exception {

                    if (useCache) {
                        String key = wrap.filters.get(0).getClass().getName()+imageView.getId();

                        if (memCache.get(key)==null) {

                            ImageProcessor imageProcessor = wrap.filters.get(0).filter(image.getProcessor());
                            memCache.put(key,imageProcessor.getImage().toBitmap());

                            return imageProcessor;
                        } else {

                            image.getProcessor().getImage().setBitmap(memCache.get(key));
                            return image.getProcessor();
                        }
                    } else {

                        return wrap.filters.get(0).filter(image.getProcessor());
                    }
                }
            }).compose(RxImageData.toMain()).subscribe(new Consumer<ImageProcessor>() {
                @Override
                public void accept(@NonNull ImageProcessor processor) throws Exception {
                    imageView.setImageBitmap(processor.getImage().toBitmap());
                }
            });

        } else {

            this.flowable.map(new Function<WrappedCV4JImage,List<CommonFilter>>() {
                @Override
                public List<CommonFilter> apply(@NonNull WrappedCV4JImage wrap) throws Exception {
                    return wrap.filters;
                }
            }).map(new Function<List<CommonFilter>,ImageProcessor>() {
                @Override
                public ImageProcessor apply(@NonNull List<CommonFilter> filters) throws Exception {
                    return filter(image.getProcessor());
                }
            }).compose(RxImageData.toMain()).subscribe(new Consumer<ImageProcessor>() {
                @Override
                public void accept(@NonNull ImageProcessor processor) throws Exception {
                    imageView.setImageBitmap((processor.getImage().toBitmap()));
                }
            });
        }
    }

    private ImageProcessor filter(ImageProcessor imageData) {

        if (filters.size()>0) {
            return filter(imageData,filters.size());
        }

        return imageData;
    }

    private ImageProcessor filter(ImageProcessor imageData, int size) {

        if (size==1) {
            CommonFilter filter = filters.get(0);
            return filter.filter(imageData);
        }

        CommonFilter filter = filters.get(size-1);
        imageData = filter.filter(imageData);

        return filter(imageData,size-1);
    }

    /**
     * 
     * @param <T>
     * @return
     */
    private static <T> FlowableTransformer<T, T> toMain() {

        return new FlowableTransformer<T, T>() {

            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}

@@ -1686,16 +1686,27 @@
   * %E4%BD%BF%E7%94%A8%E6%BB%A4%E9%95%9C
+%EF%BC%8C%E6%94%AF%E6%8C%81%E9%93%BE%E5%BC%8F%E8%B0%83%E7%94%A8%E5%A4%9A%E4%B8%AA%E6%BB%A4%E9%95%9C
 %0A     * 
@@ -2010,14 +2010,43 @@
 %E9%BB%98%E8%AE%A4%E6%83%85%E5%86%B5
+%E4%B8%8B%E6%98%AF
 %E4%BD%BF%E7%94%A8%E7%BC%93%E5%AD%98%E3%80%82%0A
+     * %E8%AF%A5%E6%96%B9%E6%B3%95%E9%9C%80%E8%A6%81%E5%9C%A8into()%E6%96%B9%E6%B3%95%E4%B9%8B%E5%89%8D%E4%BD%BF%E7%94%A8%E3%80%82%0A
     
@@ -2423,32 +2423,67 @@
 ender();%0A    %7D%0A%0A
+    /**%0A     * %E6%B8%B2%E6%9F%93imageview%0A     */%0A
     private void
@@ -3311,16 +3311,22 @@
 ss().get
+Simple
 Name()+i

add commit