package com.turlir.abakgists.allgists;

import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
import com.turlir.abakgists.api.Repository;
import com.turlir.abakgists.api.data.GistLocal;
import com.turlir.abakgists.api.data.GistMapper;
import com.turlir.abakgists.model.GistModel;

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

import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.functions.Func2;
import timber.log.Timber;

public class GistListInteractor {

    static final int IGNORE_SIZE = -1;
    private static final float PAGE_SIZE = 30;

    private final Repository mRepo;
    private final List<GistModel> mData;
    private final GistMapper.Local mTransformer;

    public GistListInteractor(Repository repo) {
        mRepo = repo;
        mData = new ArrayList<>();
        mTransformer = new GistMapper.Local();
    }

    List<GistModel> accumulator() {
        return new ArrayList<>(mData); // shadow copy
    }

    void resetAccumulator() {
        mData.clear();
    }

    /**
     * Извлекает данные из кеша, при необходимости загружает их с сервера
     *
     * @param size количество уже загруженных элементов
     * @return элементы представления
     */
    Observable<List<GistModel>> request(final int size) {
        if (size == 0) {
            mTransformer.setLocal(true);
        }

        return mRepo.load()
                .flatMap(new Func1<List<GistLocal>, Observable<List<GistLocal>>>() {
                    @Override
                    public Observable<List<GistLocal>> call(List<GistLocal> gistModels) {
                        if (gistModels.size() < size + 1) {
                            mTransformer.setLocal(false);
                            int page = Math.round(size / PAGE_SIZE) + 1;
                            return mRepo.server(page);
                        } else {
                            return Observable.just(gistModels);
                        }
                    }
                })
                .distinctUntilChanged(new Func2<List<GistLocal>, List<GistLocal>, Boolean>() {
                    @Override
                    public Boolean call(List<GistLocal> gistLocals, List<GistLocal> gistLocals2) {
                        // предотвращаем повторное прохождение результата
                        // учитывая что из БД возвращаются все записи, а не только новые
                        return gistLocals.size() == gistLocals2.size();
                    }
                })
                .map(new Func1<List<GistLocal>, List<GistModel>>() {
                    @Override
                    public List<GistModel> call(List<GistLocal> gistLocals) {
                        final int originCacheSize = mData.size();

                        for (int i = 0; i < gistLocals.size(); i++) {
                            final GistLocal item = gistLocals.get(i);

                            if (i + 1 > originCacheSize) { // новые данные в БД
                                GistModel m = mTransformer.call(item);
                                mData.add(m);

                            } else { // обновление БД
                                GistModel cache = mData.get(i);

                                boolean changed =
                                        !cache.description.equals(item.description) ||
                                        !cache.note.equals(item.note);

                                if (changed) {
                                    Timber.d("%s recreated", cache);
                                    mTransformer.setLocal(mData.get(i).isLocal);
                                    mData.set(i, mTransformer.call(item));
                                    // только один элемент из набора может измениться с обновлением
                                    i = originCacheSize;
                                }
                            }
                        }

                        return mData;
                    }
                });
    }
    /**
     * Обнвляет данные. Скачивает свежие данные с сервра, перезаписывает локальную базу
     *
     * @return сведения о записанных элементах
     */
    Observable<PutResults<GistLocal>> update() {
        mTransformer.setLocal(false);
        return mRepo.reload()
                .doOnNext(new Action1<PutResults<GistLocal>>() {
                    @Override
                    public void call(PutResults<GistLocal> gistLocalPutResults) {
                        // сохраняем кеш в RAM до успешного завершения сетевого запроса
                        mData.clear();
                    }
                });
    }
}

@@ -420,35 +420,8 @@
 c1;%0A
-import rx.functions.Func2;%0A
 impo
@@ -1982,508 +1982,8 @@
  %7D)%0A
-                .distinctUntilChanged(new Func2%3CList%3CGistLocal%3E, List%3CGistLocal%3E, Boolean%3E() %7B%0A                    @Override%0A                    public Boolean call(List%3CGistLocal%3E gistLocals, List%3CGistLocal%3E gistLocals2) %7B%0A                        // %D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%89%D0%B0%D0%B5%D0%BC %D0%BF%D0%BE%D0%B2%D1%82%D0%BE%D1%80%D0%BD%D0%BE%D0%B5 %D0%BF%D1%80%D0%BE%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5 %D1%80%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%D0%B0%0A                        // %D1%83%D1%87%D0%B8%D1%82%D1%8B%D0%B2%D0%B0%D1%8F %D1%87%D1%82%D0%BE %D0%B8%D0%B7 %D0%91%D0%94 %D0%B2%D0%BE%D0%B7%D0%B2%D1%80%D0%B0%D1%89%D0%B0%D1%8E%D1%82%D1%81%D1%8F %D0%B2%D1%81%D0%B5 %D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8, %D0%B0 %D0%BD%D0%B5 %D1%82%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE %D0%BD%D0%BE%D0%B2%D1%8B%D0%B5%0A                        return gistLocals.size() == gistLocals2.size();%0A                    %7D%0A                %7D)%0A
     

fix code