package com.novel.read.service;

import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.Nullable;

import com.mango.mangolib.event.EventManager;
import com.novel.read.R;
import com.novel.read.base.BaseService;
import com.novel.read.event.DeleteResponseEvent;
import com.novel.read.event.DeleteTaskEvent;
import com.novel.read.event.RxBus;
import com.novel.read.http.AccountManager;
import com.novel.read.model.db.BookChapterBean;
import com.novel.read.model.db.DownloadTaskBean;
import com.novel.read.model.db.dbManage.BookManager;
import com.novel.read.model.db.dbManage.BookRepository;
import com.novel.read.utlis.LocalManageUtil;
import com.novel.read.utlis.NetworkUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;

public class DownloadService extends BaseService {
    private static final String TAG = "DownloadService";
    //加载状态
    private static final int LOAD_ERROR = -1;
    private static final int LOAD_NORMAL = 0;
    private static final int LOAD_PAUSE = 1;
    private static final int LOAD_DELETE = 2; //正在加载时候，用户删除收藏书籍的情况。

    //下载状态
    public static final int STATUS_CONTINUE = DownloadTaskBean.STATUS_LOADING;
    public static final int STATUS_PAUSE = DownloadTaskBean.STATUS_PAUSE;

    //线程池
    private final ExecutorService mSingleExecutor = Executors.newSingleThreadExecutor();
    //加载队列
    private final List<DownloadTaskBean> mDownloadTaskQueue = Collections.synchronizedList(new ArrayList<>());
    //Handler
    private Handler mHandler;

    //包含所有的DownloadTask
    private List<DownloadTaskBean> mDownloadTaskList;

    private OnDownloadListener mDownloadListener;
    private boolean isBusy = false;
    private boolean isCancel = false;

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocalManageUtil.setLocal(base));
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler(getMainLooper());
        //从数据库中获取所有的任务
        mDownloadTaskList = BookRepository
                .getInstance()
                .getDownloadTaskList();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new TaskBuilder();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        //接受创建的DownloadTask
        Disposable disposable = RxBus.getInstance()
                .toObservable(DownloadTaskBean.class)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        (event) -> {
                            //判断任务是否为轮询标志
                            //判断任务是否存在，并修改任务
                            if (TextUtils.isEmpty(event.getBookId()) || !checkAndAlterDownloadTask(event)) {
                                addToExecutor(event);
                            }
                        }
                );
        addDisposable(disposable);

        //是否删除数据的问题
        Disposable deleteDisp = RxBus.getInstance()
                .toObservable(DeleteTaskEvent.class)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        (event) -> {
                            //判断是否该数据存在加载列表中
                            boolean isDelete = true;
                            for (DownloadTaskBean bean : mDownloadTaskQueue) {
                                if (bean.getBookId().equals(event.getCollBook().getId())) {
                                    isDelete = false;
                                    break;
                                }
                            }
                            //如果不存在则删除List中的task
                            if (isDelete) {
                                //
                                Iterator<DownloadTaskBean> taskIt = mDownloadTaskList.iterator();
                                while (taskIt.hasNext()) {
                                    DownloadTaskBean task = taskIt.next();
                                    if (task.getBookId().equals(event.getCollBook().getId())) {
                                        taskIt.remove();
                                    }
                                }
                            }
                            //返回状态
                            RxBus.getInstance().post(new DeleteResponseEvent(isDelete, event.getCollBook()));
                        }
                );
        addDisposable(deleteDisp);
        return super.onStartCommand(intent, flags, startId);
    }


    /**
     * 1. 查看是否任务已存在
     * 2. 修改DownloadTask的 taskName 和 list
     *
     * @return
     */
    private boolean checkAndAlterDownloadTask(DownloadTaskBean newTask) {
        boolean isExist = false;
        for (DownloadTaskBean downloadTask : mDownloadTaskList) {
            //如果不相同则不往下执行，往下执行都是存在相同的情况
            if (!downloadTask.getTaskName().equals(newTask.getTaskName())) continue;

            if (downloadTask.getStatus() == DownloadTaskBean.STATUS_FINISH) {
                //判断是否newTask是已完成
                if (downloadTask.getLastChapter() == newTask.getLastChapter()) {
                    isExist = true;
                    //发送回去已缓存
                    postMessage(getString(R.string.cached));
                }
                //判断，是否已完成的章节的起始点比新Task大，如果更大则表示新Task中的该章节已被加载，所以需要剪切
                else if (downloadTask.getLastChapter() > (newTask.getLastChapter() - newTask.getBookChapterList().size())) {
                    if (downloadTask.getLastChapter() > newTask.getLastChapter()) {
                        isExist = true;
                        //发送回去已缓存
                        postMessage(getString(R.string.cached));
                    } else {
                        //删除掉已经完成的章节
                        List<BookChapterBean> remainChapterBeans = newTask.getBookChapterList().subList(downloadTask.getLastChapter(), newTask.getLastChapter());
                        String taskName = newTask.getTaskName()
                                + getString(R.string.download_chapter_scope,
                                downloadTask.getLastChapter(), newTask.getLastChapter());
                        //重置任务
                        newTask.setBookChapters(remainChapterBeans);
                        newTask.setTaskName(taskName);

                        //发送添加到任务的提示
                        postMessage(getString(R.string.cache_success));
                    }
                }
            }
            //表示该任务已经在 下载、等待、暂停、网络错误中
            else {
                isExist = true;
                //发送回去:已经在加载队列中。
                postMessage(getString(R.string.task_exist));
            }
        }
        //重置名字
        if (!isExist) {
            String taskName = newTask.getTaskName()
                    + getString(R.string.download_chapter_scope,
                    1, newTask.getLastChapter());
            newTask.setTaskName(taskName);
            postMessage(getString(R.string.cache_success));
        }
        return isExist;
    }

    private void addToExecutor(DownloadTaskBean taskEvent) {

        //判断是否为轮询请求
        if (!TextUtils.isEmpty(taskEvent.getBookId())) {

            if (!mDownloadTaskList.contains(taskEvent)) {
                //加入总列表中，表示创建，修改CollBean的状态。
                mDownloadTaskList.add(taskEvent);
            }
            // 添加到下载队列
            mDownloadTaskQueue.add(taskEvent);
        }

        // 从队列顺序取出第一条下载
        if (mDownloadTaskQueue.size() > 0 && !isBusy) {
            isBusy = true;
            executeTask(mDownloadTaskQueue.get(0));
        }
    }

    private void executeTask(DownloadTaskBean taskEvent) {
        Runnable runnable = () -> {

            taskEvent.setStatus(DownloadTaskBean.STATUS_LOADING);

            int result = LOAD_NORMAL;
            List<BookChapterBean> bookChapterBeans = taskEvent.getBookChapters();

            //调用for循环，下载数据  //todo
//            for (int i=taskEvent.getCurrentChapter(); i<bookChapterBeans.size();++i) {
            for (int i = taskEvent.getCurrentChapter(); i <= taskEvent.getLastChapter() && i < bookChapterBeans.size(); ++i) {

                BookChapterBean bookChapterBean = bookChapterBeans.get(i);
                //首先判断该章节是否曾经被加载过 (从文件中判断)
                if (BookManager.isChapterCached(taskEvent.getBookId(), bookChapterBean.getTitle())) {

                    //设置任务进度
                    taskEvent.setCurrentChapter(i);

                    //章节加载完成
                    postDownloadChange(taskEvent, DownloadTaskBean.STATUS_LOADING, i + "");

                    //无需进行下一步
                    continue;
                }

                //判断网络是否出问题
                if (!NetworkUtils.INSTANCE.isAvailable()) {
                    //章节加载失败
                    result = LOAD_ERROR;
                    break;
                }

                if (isCancel) {
                    result = LOAD_PAUSE;
                    isCancel = false;
                    break;
                }

                //加载数据
                result = loadChapter(taskEvent.getBookId(), bookChapterBean);
                //章节加载完成
                if (result == LOAD_NORMAL) {
                    taskEvent.setCurrentChapter(i);
                    postDownloadChange(taskEvent, DownloadTaskBean.STATUS_LOADING, i + "");
                }
                //章节加载失败
                else {
                    //遇到错误退出
                    break;
                }
            }


            if (result == LOAD_NORMAL) {
                //存储DownloadTask的状态
                taskEvent.setStatus(DownloadTaskBean.STATUS_FINISH);//Task的状态
                taskEvent.setCurrentChapter(taskEvent.getBookChapters().size());//当前下载的章节数量
                taskEvent.setSize(BookManager.getBookSize(taskEvent.getBookId()));//Task的大小

                //发送完成状态
                postDownloadChange(taskEvent, DownloadTaskBean.STATUS_FINISH, getString(R.string.download_success));
            } else if (result == LOAD_ERROR) {
                taskEvent.setStatus(DownloadTaskBean.STATUS_ERROR);//Task的状态
                //任务加载失败
                postDownloadChange(taskEvent, DownloadTaskBean.STATUS_ERROR, getString(R.string.download_error));
            } else if (result == LOAD_PAUSE) {
                taskEvent.setStatus(DownloadTaskBean.STATUS_PAUSE);//Task的状态
                postDownloadChange(taskEvent, DownloadTaskBean.STATUS_PAUSE, getString(R.string.download_pause));
            } else if (result == LOAD_DELETE) {
                //没想好怎么做
            }

            //存储状态
            BookRepository.getInstance().saveDownloadTask(taskEvent);

            //轮询下一个事件，用RxBus用来保证事件是在主线程

            //移除完成的任务
            mDownloadTaskQueue.remove(taskEvent);
            //设置为空闲
            isBusy = false;
            //轮询
            post(new DownloadTaskBean());
        };
        mSingleExecutor.execute(runnable);
    }

    private int loadChapter(String folderName, BookChapterBean bean) {
        //加载的结果参数
        final int[] result = {LOAD_NORMAL};

        //问题:(这里有个问题，就是body其实比较大，如何获取数据流而不是对象，)是不是直接使用OkHttpClient交互会更好一点
        Disposable disposable = AccountManager.Companion.getInstance()
                .getChapterInfo(bean.getId())
                //表示在当前环境下执行
                .subscribe(
                        chapterInfo -> {
                            //TODO:这里文件的名字用的是BookChapter的title,而不是chapter的title。
                            //原因是Chapter的title可能重复，但是BookChapter的title不会重复
                            //BookChapter的title = 卷名 + 章节名 chapter 的 title 就是章节名。。
                            BookRepository.getInstance().saveChapterInfo(folderName, bean.getTitle(), chapterInfo.getBody());
                        },
                        e -> {
                            //当前进度加载错误（这里需要判断是什么问题，根据相应的问题做出相应的回答）
                            Log.e(TAG, "loadChapter: " + e);
                            //设置加载结果
                            result[0] = LOAD_ERROR;
                        }
                );
        addDisposable(disposable);
        return result[0];
    }

    private void postDownloadChange(DownloadTaskBean task, int status, String msg) {
        if (mDownloadListener != null && msg != null) {
            int position = mDownloadTaskList.indexOf(task);
            //通过handler,切换回主线程
            mHandler.post(() -> mDownloadListener.onDownloadChange(
                    position, status, msg)
            );
        }
    }

    private void postMessage(String msg) {
//        RxBus.getInstance().post(new DownloadMessage(msg));
        EventManager.Companion.getInstance().postEvent(new DownloadMessage(msg));
    }

    private void post(DownloadTaskBean task) {
        RxBus.getInstance().post(task);
    }


    @Override
    public boolean onUnbind(Intent intent) {

        mDownloadListener = null;
        return super.onUnbind(intent);
    }

    class TaskBuilder extends Binder implements IDownloadManager {
        @Override
        public List<DownloadTaskBean> getDownloadTaskList() {
            return Collections.unmodifiableList(mDownloadTaskList);
        }

        @Override
        public void setOnDownloadListener(OnDownloadListener listener) {
            mDownloadListener = listener;
        }

        @Override
        public void setDownloadStatus(String taskName, int status) {
            //修改某个Task的状态
            switch (status) {
                //加入缓存队列
                case DownloadTaskBean.STATUS_WAIT:
                    for (int i = 0; i < mDownloadTaskList.size(); ++i) {
                        DownloadTaskBean bean = mDownloadTaskList.get(i);
                        if (taskName.equals(bean.getTaskName())) {
                            bean.setStatus(DownloadTaskBean.STATUS_WAIT);
                            mDownloadListener.onDownloadResponse(i, DownloadTaskBean.STATUS_WAIT);
                            addToExecutor(bean);
                            break;
                        }
                    }
                    break;
                //从缓存队列中删除
                case DownloadTaskBean.STATUS_PAUSE:
                    Iterator<DownloadTaskBean> it = mDownloadTaskQueue.iterator();
                    while (it.hasNext()) {
                        DownloadTaskBean bean = it.next();
                        if (bean.getTaskName().equals(taskName)) {
                            if (bean.getStatus() == DownloadTaskBean.STATUS_LOADING
                                    && bean.getTaskName().equals(taskName)) {
                                isCancel = true;
                                break;
                            } else {
                                bean.setStatus(DownloadTaskBean.STATUS_PAUSE);
                                mDownloadTaskQueue.remove(bean);
                                int position = mDownloadTaskList.indexOf(bean);
                                mDownloadListener.onDownloadResponse(position, DownloadTaskBean.STATUS_PAUSE);
                                break;
                            }
                        }
                    }
                    break;
            }
        }

        @Override
        public void setAllDownloadStatus(int status) {
            //修改所有Task的状态
        }

        //首先判断是否在加载队列中。
        //如果在加载队列中首先判断是否正在下载，
        //然后判断是否在完成队列中。
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    public interface IDownloadManager {
        List<DownloadTaskBean> getDownloadTaskList();

        void setOnDownloadListener(OnDownloadListener listener);

        void setDownloadStatus(String taskName, int status);

        void setAllDownloadStatus(int status);
    }

    public interface OnDownloadListener {
        /**
         * @param pos    : Task在item中的位置
         * @param status : Task的状态
         * @param msg:   传送的Msg
         */
        void onDownloadChange(int pos, int status, String msg);

        /**
         * 回复
         */
        void onDownloadResponse(int pos, int status);
    }
}
