package com.datarecovery.master.module.filerecover;

import static com.datarecovery.master.data.consts.EventId.EVENT_3000004;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;

import com.atmob.app.lib.base.BaseViewModel;
import com.atmob.app.lib.livedata.SingleLiveEvent;
import com.atmob.common.runtime.ContextUtil;
import com.datarecovery.master.R;
import com.datarecovery.master.data.consts.AdFuncId;
import com.datarecovery.master.data.consts.EventId;
import com.datarecovery.master.data.repositories.DeviceFuncRepository;
import com.datarecovery.master.handler.EventHelper;
import com.datarecovery.master.sdk.ad.AtmobAdHelper;
import com.datarecovery.master.sdk.bugly.BuglyHelper;
import com.datarecovery.master.utils.BoxingUtil;
import com.datarecovery.master.utils.FileUtil;
import com.datarecovery.master.utils.FilesSearch;
import com.datarecovery.master.utils.MediaStoreHelper;
import com.datarecovery.master.utils.ReverseArrayList;
import com.datarecovery.master.utils.ToastUtil;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import atmob.reactivex.rxjava3.annotations.NonNull;
import atmob.reactivex.rxjava3.core.Single;
import atmob.reactivex.rxjava3.core.SingleObserver;
import atmob.reactivex.rxjava3.disposables.Disposable;
import atmob.rxjava.utils.RxJavaUtil;
import dagger.hilt.android.lifecycle.HiltViewModel;


@HiltViewModel
public class FileRecoverViewModel extends BaseViewModel {

    private final long SCANNING_COUNTDOWN = 1000 * 60 * 6;

    private final long SCANNING_IS_TRIAL_COUNTDOWN = 1000 * 5;

    private final int[] tabTitle = {R.string.word, R.string.excel, R.string.ppt, R.string.pdf};

    private final List<MutableLiveData<Boolean>> checkList = new ArrayList<>();
    private final List<FilesSearch.DocumentFile> wordList = new ReverseArrayList<>();
    private final List<FilesSearch.DocumentFile> excelList = new ReverseArrayList<>();
    private final List<FilesSearch.DocumentFile> pptList = new ReverseArrayList<>();
    private final List<FilesSearch.DocumentFile> pdfList = new ReverseArrayList<>();
    private final List<FilesSearch.DocumentFile> selectList = new ArrayList<>();


    private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedWordList = new MutableLiveData<>();
    private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedExcelList = new MutableLiveData<>();
    private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedPPTList = new MutableLiveData<>();
    private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedPDFList = new MutableLiveData<>();
    private final MutableLiveData<List<FilesSearch.DocumentFile>> selectedList = new MutableLiveData<>(selectList);

    private final SingleLiveEvent<?> scrollTop = new SingleLiveEvent<>();
    private final MutableLiveData<Boolean> showTrialView = new MutableLiveData<>();
    private final MutableLiveData<String> detectedLastFileName = new MutableLiveData<>();
    private final MutableLiveData<Integer> checkPosition = new MutableLiveData<>();
    private final SingleLiveEvent<Boolean> showLoadingEvent = new SingleLiveEvent<>();
    private final SingleLiveEvent<Boolean> showScanDialogEvent = new SingleLiveEvent<>();
    private final SingleLiveEvent<?> showUnlockEvent = new SingleLiveEvent<>();
    private final DeviceFuncRepository deviceFuncRepository;
    private final LiveData<String> selectedCountTxt;
    private Disposable scanDisposable;

    @Inject
    public FileRecoverViewModel(DeviceFuncRepository deviceFuncRepository) {
        this.deviceFuncRepository = deviceFuncRepository;
        selectedCountTxt = Transformations.map(selectedList, list -> {
            if (list == null || list.isEmpty()) {
                return ContextUtil.getContext().getString(R.string.export);
            }
            return ContextUtil.getContext().getString(R.string.export_count, list.size());
        });
        for (int i = 0; i < tabTitle.length; i++) checkList.add(new MutableLiveData<>(false));
    }

    public LiveData<?> getScrollTop() {
        return scrollTop;
    }

    public LiveData<Boolean> getShowTrialView() {
        return showTrialView;
    }

    public LiveData<String> getDetectedLastFileName() {
        return detectedLastFileName;
    }

    public LiveData<Integer> getCheckPosition() {
        return checkPosition;
    }

    public void setCheckPosition(int position) {
        this.checkPosition.setValue(position);
    }

    public int[] getTabTitle() {
        return tabTitle;
    }

    public LiveData<List<FilesSearch.DocumentFile>> getDetectedWordList() {
        return detectedWordList;
    }

    public LiveData<List<FilesSearch.DocumentFile>> getDetectedExcelList() {
        return detectedExcelList;
    }

    public LiveData<List<FilesSearch.DocumentFile>> getDetectedPPTList() {
        return detectedPPTList;
    }

    public LiveData<List<FilesSearch.DocumentFile>> getDetectedPDFList() {
        return detectedPDFList;
    }

    public LiveData<Boolean> getShowLoadingEvent() {
        return showLoadingEvent;
    }

    public LiveData<List<FilesSearch.DocumentFile>> getSelectedList() {
        return selectedList;
    }

    public LiveData<String> getSelectedCountTxt() {
        return selectedCountTxt;
    }

    public LiveData<Boolean> getShowScanDialogEvent() {
        return showScanDialogEvent;
    }

    public LiveData<?> getShowUnlockEvent() {
        return showUnlockEvent;
    }

    public void startFileScanning() {
        if (scanDisposable != null && !scanDisposable.isDisposed()) {
            return;
        }
        FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.WORD, FilesSearch.DocumentFile.EXCEL, FilesSearch.DocumentFile.PPT, FilesSearch.DocumentFile.PDF)
                .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<List<FilesSearch.DocumentFile>>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(Integer.MAX_VALUE);
                        scanDisposable = Disposable.fromSubscription(s);
                        addDisposable(scanDisposable);
                        showScanDialogEvent.setValue(true);
                        wordList.clear();
                        excelList.clear();
                        pptList.clear();
                        pdfList.clear();
                        selectList.clear();
                    }

                    @Override
                    public void onNext(List<FilesSearch.DocumentFile> documentFiles) {
                        if (documentFiles == null || documentFiles.isEmpty()) {
                            return;
                        }
                        int wordCount = 0;
                        int excelCount = 0;
                        int pptCount = 0;
                        int pdfCount = 0;
                        for (FilesSearch.DocumentFile item : documentFiles) {
                            detectedLastFileName.setValue(item.getName());
                            if (item.getCategory() == FilesSearch.DocumentFile.WORD) {
                                wordCount++;
                                wordList.add(item);
                            } else if (item.getCategory() == FilesSearch.DocumentFile.EXCEL) {
                                excelCount++;
                                excelList.add(item);
                            } else if (item.getCategory() == FilesSearch.DocumentFile.PPT) {
                                pptCount++;
                                pptList.add(item);
                            } else if (item.getCategory() == FilesSearch.DocumentFile.PDF) {
                                pdfCount++;
                                pdfList.add(item);
                            }
                        }
                        if (wordCount > 0) {
                            detectedWordList.setValue(wordList);
                        }
                        if (excelCount > 0) {
                            detectedExcelList.setValue(excelList);
                        }
                        if (pptCount > 0) {
                            detectedPPTList.setValue(pptList);
                        }
                        if (pdfCount > 0) {
                            detectedPDFList.setValue(pdfList);
                        }
                        scrollTop.call();
                    }

                    @Override
                    public void onError(Throwable t) {
                        showScanDialogEvent.setValue(false);
                    }

                    @Override
                    public void onComplete() {
                        showScanDialogEvent.setValue(false);
                    }
                });
    }

    public void cancelScan() {
        if (scanDisposable != null && !scanDisposable.isDisposed()) scanDisposable.dispose();
        showScanDialogEvent.setValue(false);
    }

    public void onCheckAllClick(boolean isCheck) {
        EventHelper.report(EventId.EVENT_3000006);
        int index = BoxingUtil.boxing(checkPosition.getValue());
        getCheckAll(index).setValue(isCheck);
        int id = tabTitle[index];
        List<FilesSearch.DocumentFile> list = null;
        if (id == R.string.word) {
            list = wordList;
        } else if (id == R.string.excel) {
            list = excelList;
        } else if (id == R.string.ppt) {
            list = pptList;
        } else if (id == R.string.pdf) {
            list = pdfList;
        }
        if (list == null || list.isEmpty()) {
            return;
        }
        for (FilesSearch.DocumentFile item : list) {
            if (item.isCheck() != isCheck) {
                if (isCheck) {
                    selectList.add(item);
                } else {
                    selectList.remove(item);
                }
            }
            item.setCheck(isCheck);
        }
        this.selectedList.setValue(selectList);
    }

    public MutableLiveData<Boolean> getCheckAll(int position) {
        return checkList.get(position);
    }

    public void onExportClick() {
        if (selectList == null || selectList.isEmpty()) {
            return;
        }
        showUnlockEvent.call();
    }

    public void doExport() {
        Single.just(selectList.size())
                .map(oldSize -> {
                    Iterator<FilesSearch.DocumentFile> iterator = selectList.iterator();
                    int errorCount = 0;
                    Exception exception = null;
                    while (iterator.hasNext()) {
                        FilesSearch.DocumentFile item = iterator.next();
                        try {
                            MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_FILES, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_FILES, item.getName()));
                            item.setCheck(false);
                            iterator.remove();
                        } catch (Exception throwable) {
                            errorCount++;
                            exception = throwable;
                            BuglyHelper.postCatchedException(new Exception("文件导出:", throwable));
                        }
                    }
                    if (errorCount == oldSize) {
                        throw new Exception("导出失败" + (exception == null ? "" : ":" + exception.getMessage()));
                    } else if (errorCount > 0) {
                        throw new Exception("部分导出失败" + ":" + exception.getMessage());
                    }
                    return errorCount;
                })
                .compose(RxJavaUtil.SingleSchedule.io2Main())
                .subscribe(new SingleObserver<Integer>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        showLoadingEvent.setValue(true);
                        addDisposable(d);
                    }

                    @Override
                    public void onSuccess(@NonNull Integer integer) {
                        showLoadingEvent.setValue(false);
                        selectedList.setValue(selectList);
                        ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
                        getCheckAll(BoxingUtil.boxing(checkPosition.getValue())).setValue(false);
                        AtmobAdHelper.showInterstitial(AdFuncId.INTERSTITIAL_RECOVER_SUCCESS, null);
                        EventHelper.report(EVENT_3000004);
                    }

                    @Override
                    public void onError(@NonNull Throwable throwable) {
                        showLoadingEvent.setValue(false);
                        selectedList.setValue(selectList);
                        ToastUtil.show(throwable.getMessage(), ToastUtil.LENGTH_SHORT);
                    }
                });
    }

    public void itemClick(FilesSearch.DocumentFile documentFile) {
        if (documentFile == null) {
            return;
        }
        documentFile.setCheck(!documentFile.isCheck());
        if (documentFile.isCheck()) {
            selectList.add(documentFile);
        } else {
            selectList.remove(documentFile);
        }
        this.selectedList.setValue(selectList);
    }
}
