package com.gingersoft.gsa.cloud.print;

import android.os.AsyncTask;
import android.util.Log;

import com.gingersoft.gsa.cloud.common.logan.LoganManager;
import com.gingersoft.gsa.cloud.print.impl.OnPrjPrintResultListener;
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;

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

import io.reactivex.disposables.Disposable;

/**
 * 打印执行者
 *
 * @author admin
 */
public class PrintExecutor {
    protected final String TAG = this.getClass().getSimpleName();

    private static PrintExecutor printExecutor;

    public static PrintExecutor getInstance() {
        if (printExecutor == null) {
            printExecutor = new PrintExecutor();
        }
        return printExecutor;
    }

    private PrintSocketHolder holder;
    /**
     * 存儲所有prj的id集合
     */
    private String prjIds;
    private PrintSocketHolder.OnStateChangedListener listener;
    private OnPrintResultListener mListener;
    private OnPrjPrintResultListener onPrjPrintResultListener;

    public PrintExecutor() {
        holder = PrintSocketHolder.getInstance();
        holder.closeSocket();
        printDataMakers = new ArrayList<>();
    }

    /**
     * 需要執行的任務隊列
     */
    List<PrintDataMaker> printDataMakers;
    /**
     * 重啟打印的服務
     */
    private Disposable resetPrintDis;

    /**
     * 异步执行打印请求
     */
    public void doPrinterRequestAsync(PrintDataMaker maker) {
        if (printDataMakers.size() <= 0) {
            printDataMakers.add(maker);
            new PrintTask().execute(maker);
        } else {
            //如果隊列裡有任務在執行，只添加進去，等待執行完成之後，再來執行這個
            printDataMakers.add(maker);
            startReset();
        }
    }

    private void startReset() {
        resetPrintDis = RxJavaUtils.delay(10, aLong -> {
            //如果十秒之後，任務還沒在打印完成方法中取消，可能打印程序卡住了，在這裡執行下一個任務
            if (printDataMakers.size() > 0) {
                new PrintTask().execute(printDataMakers.get(0));
            }
        });
    }

    /**
     * 执行打印请求
     *
     * @return 错误代码
     */
    private int doRequest(PrintDataMaker maker) {
        //通知狀態
        holder.onPrinterStateChanged(PrintSocketHolder.STATE_0);
        //獲取打印數據
        List<byte[]> data = maker.getPrintData();
        //如果是打印prj，需要獲取prj的id
        prjIds = maker.getPrjIds();
        //判斷是否連接，如果未連接就先連接
        int prepare = holder.prepareSocket(maker.getIp(), maker.getPort());
        if (prepare != PrintSocketHolder.ERROR_0) {
            return prepare;
        }
        return holder.sendData(data);
    }

    /**
     * 打印任務
     */
    private class PrintTask extends AsyncTask<PrintDataMaker, Integer, Integer> implements
            PrintSocketHolder.OnStateChangedListener {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.e("eee", "任務數量：" + printDataMakers.size());
            holder.setOnStateChangedListener(this);
        }

        @Override
        protected Integer doInBackground(PrintDataMaker... makers) {
            holder.closeSocket();
            if (makers == null || makers.length < 1) {
                return PrintSocketHolder.ERROR_0;
            }
            return doRequest(makers[0]);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (values == null || values.length < 1) {
                return;
            }
            if (listener != null) {
                listener.onStateChanged(values[0]);
            }
        }

        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            if (resetPrintDis != null) {
                resetPrintDis.dispose();
            }
            //移除掉當前任務
            if (printDataMakers.size() > 0) {
                printDataMakers.remove(0);
            }
            //執行下一個任務
            if (printDataMakers.size() > 0) {
                new PrintTask().execute(printDataMakers.get(0));
                startReset();
            }
            Log.e("eee", "完成後任務數量：" + printDataMakers.size());
            //返回結果
            if (integer != null) {
                onResult(integer);
            }
        }

        /**
         * 打印结果
         *
         * @param errorCode 错误代码
         */
        private void onResult(int errorCode) {
            try {
                if (mListener != null) {
                    mListener.onResult(errorCode);
                }
                if (onPrjPrintResultListener != null) {
                    onPrjPrintResultListener.onResult(errorCode, prjIds);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onStateChanged(int state) {
            switch (state) {
                case PrintSocketHolder.STATE_0:
                    LoganManager.w_printer(TAG, "打印機狀態 --> 生成页面数据");
                    break;
                case PrintSocketHolder.STATE_1:
                    LoganManager.w_printer(TAG, "打印機狀態 --> 创建Socket连接");
                    break;
                case PrintSocketHolder.STATE_2:
                    LoganManager.w_printer(TAG, "打印機狀態 --> 获取输出流");
                    break;
                case PrintSocketHolder.STATE_3:
                    LoganManager.w_printer(TAG, "打印機狀態 --> 写入页面数据");
                    break;
                case PrintSocketHolder.STATE_4:
                    LoganManager.w_printer(TAG, "打印機狀態 --> 关闭输出流");
                    break;
                default:
                    break;
            }
            publishProgress(state);
        }
    }

    /**
     * 设置状态监听
     *
     * @param listener 监听
     */
    public PrintExecutor setOnStateChangedListener(PrintSocketHolder.OnStateChangedListener listener) {
        this.listener = listener;
        return this;
    }

    /**
     * 设置结果回调
     *
     * @param listener 回调
     */
    public PrintExecutor setOnPrintResultListener(OnPrintResultListener listener) {
        this.mListener = listener;
        return this;
    }

    /**
     * 打印結果回調
     */
    public interface OnPrintResultListener {
        void onResult(int errorCode);
    }

    public PrintExecutor setOnPrjPrintResultListener(OnPrjPrintResultListener onPrjPrintResultListener) {
        this.onPrjPrintResultListener = onPrjPrintResultListener;
        return this;
    }
}
