package com.joe.print.mvp.ui.activity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.billy.cc.core.component.CC;
import com.billy.cc.core.component.CCResult;
import com.billy.cc.core.component.CCUtil;
import com.gingersoft.gsa.cloud.common.constans.PrintConstans;
import com.gingersoft.gsa.cloud.common.logan.LoganManager;
import com.gingersoft.gsa.cloud.common.printer.plugins.PrinterFlowListener;
import com.gingersoft.gsa.cloud.common.printer.plugins.PrinterFlowProxy;
import com.gingersoft.gsa.cloud.common.utils.gson.GsonUtils;
import com.gingersoft.gsa.cloud.common.utils.log.LogUtil;
import com.gingersoft.gsa.cloud.common.utils.other.SPUtils;
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil;
import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils;
import com.gingersoft.gsa.cloud.database.bean.PrintCurrencyBean;
import com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean;
import com.gingersoft.gsa.cloud.print.PrintExecutor;
import com.gingersoft.gsa.cloud.print.PrintSocketHolder;
import com.gingersoft.gsa.cloud.print.bean.PrintContent;
import com.gingersoft.gsa.cloud.print.bean.PrjBean;
import com.gyf.immersionbar.ImmersionBar;
import com.jess.arms.base.BaseActivity;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.utils.ArmsUtils;
import com.joe.print.R;
import com.joe.print.di.component.DaggerPrintComponent;
import com.joe.print.mvp.contract.PrintContract;
import com.joe.print.mvp.presenter.PrintPresenter;
import com.joe.print.mvp.print.PrintInstruction;
import com.joe.print.mvp.print.PrintPrjKitchen;
import com.joe.print.mvp.print.PrinterRoot;
import com.joe.print.mvp.print.maker.OpenCashBoxMaker;
import com.joe.print.mvp.print.utils.MyPrintUtils;
import com.joe.print.mvp.ui.view.PrinterLoadingDialog;
import com.joe.print.mvp.ui.view.SelectPrintDevicePopup;
import com.lxj.xpopup.XPopup;
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;

import java.util.List;
import java.util.Map;

import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_BILL;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_CLOSING;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_ORDER;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_SLIP;
import static com.jess.arms.utils.Preconditions.checkNotNull;

/**
 * ================================================
 * Description:
 * <p>
 * Created by MVPArmsTemplate on 01/18/2020 14:57
 * <a href="mailto:jess.yan.effort@gmail.com">Contact me</a>
 * <a href="https://github.com/JessYanCoding">Follow me</a>
 * <a href="https://github.com/JessYanCoding/MVPArms">Star me</a>
 * <a href="https://github.com/JessYanCoding/MVPArms/wiki">See me</a>
 * <a href="https://github.com/JessYanCoding/MVPArmsTemplate">模版请保持更新</a>
 * ================================================
 * 透明activity
 * 打印入口
 * 選擇打印方式
 * ----本機打印
 * ----調用本機打印方法
 * ----網絡打印
 * ----獲取網絡打印機列表
 */
public class PrintActivity extends BaseActivity<PrintPresenter> implements PrintContract.View, PrintExecutor.OnPrintResultListener {

    public final static int ADD_PRINT_CODE = 1001;//添加打印機回調


    public static List<PrinterDeviceBean> printerDeviceBeans;
    private String callId;
    private PrinterRoot printerInIt;

    /**
     * 0：上菜紙
     * 1：印單
     * 2：結賬單
     * 3：廚房單
     * 4：打印view
     * 5：打印外賣接單
     * 6：其他指令
     */
    private int type;
    private String mOrderNo;

    private PrinterLoadingDialog printerLoadingDialog;

    private boolean printerResult;

    @Override
    public void setupActivityComponent(@NonNull AppComponent appComponent) {
        LoganManager.w_code(TAG, "setupActivityComponent");
        DaggerPrintComponent //如找不到该类,请编译一下项目
                .builder()
                .appComponent(appComponent)
                .view(this)
                .build()
                .inject(this);
    }

    @Override
    public int initView(@Nullable Bundle savedInstanceState) {
        LoganManager.w_code(TAG, "initView");
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
        return 0;//R.layout.print_bitmap;如果你不需要框架帮你设置 setContentView(id) 需要 自行设置,请返回 0
    }

    @Override
    public void configImmersionBar(ImmersionBar immersionBar) {
        LoganManager.w_code(TAG, "configImmersionBar");
        immersionBar
                .fitsSystemWindows(true)
                .statusBarColor(R.color.trans)
                .statusBarDarkFont(true)
                .init();
    }

    @Override
    public void initData(@Nullable Bundle savedInstanceState) {
        LoganManager.w_code(TAG, "initData");
        PrinterFlowProxy.newInstance().registerPrinterFlowListener(printerFlowListener);
    }

    private PrinterFlowListener printerFlowListener = new PrinterFlowListener() {
        @Override
        public void connectionBefore(String deviceName, String IP, int port, long ioTimeout, long printTimeout) {

        }

        @Override
        public void connectionSuccess() {
            if (printerLoadingDialog == null) {
                return;
            }
            printerLoadingDialog.setStep(PrinterLoadingDialog.PROGRESS_PRINTING, PrinterLoadingDialog.STATUS_SUCCESS, null);
        }

        @Override
        public void connectionError(Exception e) {
            if (printerLoadingDialog == null) {
                return;
            }
            printerLoadingDialog.setStep(PrinterLoadingDialog.PROGRESS_PRINTING, PrinterLoadingDialog.STATUS_ERROR, e.getMessage());
            printFail();
        }

        @Override
        public void disconnect(Exception e) {
        }

        @Override
        public void onPrinterDataBefore(int orderType, int printType, String printerData, String printerDeviceInfo) {
            if (printerLoadingDialog == null) {
                return;
            }
            printerLoadingDialog.setStep(PrinterLoadingDialog.PROGRESS_CONNECTING, PrinterLoadingDialog.STATUS_SUCCESS, null);
        }

        @Override
        public void onPrinterBitmapBefore(int orderType, int printType, String directoryName, List<Bitmap> bitmaps) {
            if (printerLoadingDialog == null) {
                return;
            }
            printerLoadingDialog.setStep(PrinterLoadingDialog.PROGRESS_CONNECTING, PrinterLoadingDialog.STATUS_SUCCESS, null);
        }

        @Override
        public void onPrintSuccess() {
            printerResult = true;
            if (printerLoadingDialog == null) {
                return;
            }
            printerLoadingDialog.setStep(PrinterLoadingDialog.PROGRESS_RESULT, PrinterLoadingDialog.STATUS_SUCCESS, null);
            printSuccess();
        }

        @Override
        public void onPrintError(Exception e, int errorCode) {
            if (printerLoadingDialog == null) {
                return;
            }
            printerLoadingDialog.setStep(PrinterLoadingDialog.PROGRESS_RESULT, PrinterLoadingDialog.STATUS_ERROR, e.getMessage());
            printFail();
        }
    };

    private void printFail() {
        printerResult = false;
        //延遲兩秒關閉
        RxJavaUtils.delay(2, aLong -> {
            LogUtil.e("eee", "打印失敗");
            CC.sendCCResult(callId, CCResult.error("print error"));
            killMyself();
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        actionPrinter();
    }

    @Override
    protected void onStart() {
        super.onStart();
        actionPrinter();
    }

//    @Override
//    protected void onResume() {
//        super.onResume();
//        actionPrinter();
//    }

    private void actionPrinter() {

        LoganManager.w_code(TAG, "actionPrinter start");

        showPrintLoadingDialog();

        callId = CCUtil.getNavigateCallId(this);
        //獲取打印類型，根據打印類型生成對應的bitmap
        type = CCUtil.getNavigateParam(this, PrintConstans.PRINT_TYPE, PrintConstans.PRINT_TEST);
        //獲取打印內容
        PrintContent printContent = CCUtil.getNavigateParam(this, PrintConstans.PRINT_CONTENT, null);
        //訂單編號
        mOrderNo = CCUtil.getNavigateParam(this, PrintConstans.PRINT_ORDER_NO, "");
        //根據打印類型獲取對應的執行類
        printerInIt = PrinterRoot.getPrinterByType(type, printContent);
        //初始化打印配置
        initPrintConfig(printContent);

        LoganManager.w_code(TAG, "actionPrinter end");
    }

    private void showPrintLoadingDialog() {
        boolean isShowLoading = CCUtil.getNavigateParam(this, PrintConstans.PRINT_SHOW_LOADING, true);
        if (printerLoadingDialog != null) {
            printerLoadingDialog = printerLoadingDialog.build();
        } else {
            printerLoadingDialog = new PrinterLoadingDialog(this).build();
        }
        printerLoadingDialog.setOnCancelListener(dialog -> {
            killMyself();
            if (printerResult) {
                CC.sendCCResult(callId, CCResult.success());
            } else {
                CC.sendCCResult(callId, CCResult.error("print error"));
            }
        });
        if (isShowLoading) {
            printerLoadingDialog.show();
        }
    }

    /**
     * 如果沒有默認打印機，彈窗彈出讓用戶選擇打印機
     */
    private PrinterDeviceBean defaultPrint;

    private void initPrintConfig(PrintContent printContent) {

        LoganManager.w_code(TAG, "initPrintConfig start");

        //開始
        PrinterFlowProxy.newInstance().dispatchPrinterDataBefore(type, type, GsonUtils.GsonString(printContent), GsonUtils.GsonString(defaultPrint));

        //獲取通用打印配置
        PrintCurrencyBean printCurrencyBean = getCurrencyConfig();
        //獲取打印機列表
        printerDeviceBeans = mPresenter.getAllPrintList(this);

        if (type == PrintConstans.PRINT_TEST) {
            //如果是打印測試，就取由頁面傳遞過來的打印機信息
            defaultPrint = CCUtil.getNavigateParam(this, "deviceBean", null);
        } else {
            // 獲取默認打印機，如果用戶沒有配置默認打印機，就取最近使用的一個.
            // 如果沒有最近使用的打印機，並且當前餐廳只有一台打印機，就用這一台打印機打印
            defaultPrint = mPresenter.getDefaultPrintInList(printerDeviceBeans, (String) SPUtils.get("defaultPrint", ""));
        }
        //如果是打印廚房單
        if (type == PrintConstans.PRINT_KITCHEN) {
            //設置廚房單的信息，並且獲取到這個廚房單的打印位置
            defaultPrint = setKitChenPrj(defaultPrint);
        }
        //如果沒有打印機
        if (defaultPrint == null) {
            //沒有默認打印機，查看當前餐廳有沒有打印機
            //如果當前餐廳有打印機，彈出彈窗讓用戶選擇一個打印機打印
            showSelectPrint(printCurrencyBean);
        } else {
            //將打印機和通用配置合併
            defaultPrint = MyPrintUtils.configPrinterProperties(printCurrencyBean, defaultPrint);
            printByDevice(defaultPrint);
        }

        LoganManager.w_code(TAG, "initPrintConfig end");
    }

    /**
     * 顯示選擇打印機
     *
     * @param printCurrencyBean
     */
    private void showSelectPrint(PrintCurrencyBean printCurrencyBean) {
        if (printerDeviceBeans != null && printerDeviceBeans.size() > 0) {
            SelectPrintDevicePopup selectPrintDevicePopup = new SelectPrintDevicePopup(mContext, printerDeviceBeans);
            selectPrintDevicePopup.setOnItemClickListener((adapter, view, position) -> {
                //用戶選擇的ip打印機打印
                //將打印機和通用配置合併
                selectPrintDevicePopup.dismiss();
                this.defaultPrint = MyPrintUtils.configPrinterProperties(printCurrencyBean, printerDeviceBeans.get(position));
                printByDevice(this.defaultPrint);
                SPUtils.put("defaultPrint", printerDeviceBeans.get(position).getName());
            }).setOnDismissListener(() -> {
                //如果彈窗已經關閉，打印機還是為空，說明用戶沒有選擇打印機
                if (this.defaultPrint == null) {
                    printFailure("沒有找到打印機，無法打印");
                }
            });
            new XPopup.Builder(mContext).asCustom(selectPrintDevicePopup).show();
        } else {
            //沒有打印機
            ToastUtils.show(mContext, "沒有打印機，請先添加打印機");
        }
    }

    /**
     * 設置廚房單打印數據
     *
     * @param defaultPrint 默認打印機
     * @return 如果prj有指定打印機，並且找到了，就返回
     */
    private PrinterDeviceBean setKitChenPrj(PrinterDeviceBean defaultPrint) {
        String prjJson = CCUtil.getNavigateParam(this, "prjBeans", null);
        List<PrjBean> printDatas = GsonUtils.jsonToList(prjJson, PrjBean.class);
//        List<PrjBean> printDatas = CCUtil.getNavigateParam(this, "prjBeans", null);
        Map<String, List<PrjBean>> prjMap = PrintPrjKitchen.getPrjMap();
        String printLocation = null;
        prjMap.put("", printDatas);
        for (PrjBean prjBean : printDatas) {
            if (printLocation == null) {
                if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getPrintPosition())) {
                    printLocation = prjBean.getPrintPosition();
                    return mPresenter.getPrinterDeviceBeanByName(printerDeviceBeans, printLocation);
                } else {
                    if (defaultPrint == null) {
                        printLocation = "";
                    } else {
                        printLocation = defaultPrint.getName();
                    }
                }
            }
            prjBean.setPrintPosition(printLocation);
            prjBean.setCurrentIndex(1);
        }
        return null;
    }

    /**
     * 獲取通用打印配置
     */
    private PrintCurrencyBean getCurrencyConfig() {
        PrintCurrencyBean printCurrencyBean;
        if (type == PRINT_OTHER_ORDER || type == PRINT_OTHER_CLOSING) {
            //外賣的通用打印配置
            printCurrencyBean = mPresenter.getPrintCurrencyBeanByType(this, PRINT_BILL);
        }
//        else if (type == 0 || type == 1 || type == 2) {
//            //堂食的通用打印配置
//            printCurrencyBean = mPresenter.getPrintCurrencyBeanByType(this, 1);
//        }
        else {
            printCurrencyBean = mPresenter.getPrintCurrencyBeanByType(this, PRINT_SLIP);
        }
        return printCurrencyBean;
    }

    /**
     * 打印邏輯，獲取對應的打印配置--打印機或是通用配置
     * 根據配置生成配置好的圖片----生成圖片邏輯：把打印的單分為幾個模塊，再由不同的單拼接出對應的單，(如果是針式，生成對應的文字)
     * 再獲取打印方式(IP、本機、USB、藍牙或其他的)，調用打印
     *
     * @param defaultPrint 打印機
     */
    private void printByDevice(PrinterDeviceBean defaultPrint) {
        LoganManager.w_code(TAG, "printByDevice start");
        //獲取對應的打印類
        if (printerInIt instanceof PrintInstruction) {
            //開錢箱
            PrintExecutor executor = new PrintExecutor();
            executor.doPrinterRequestAsync(new OpenCashBoxMaker(defaultPrint.getIp(), defaultPrint.getPort()));
            CC.sendCCResult(callId, CCResult.success());
        } else {
            Map<String, List<Bitmap>> listMap;
            List<Bitmap> zoomBitmaps = null;
            String[] BBPosPrintDatas = null;
            if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_LOCAL && PrintConstans.PRINT_MODEL_WISEPOS.contains(Build.MODEL)) {
                //本機打印並且是BBPOS
                //獲取打印數據
                BBPosPrintDatas = printerInIt.getPrintDatas(mContext, defaultPrint);
                if (BBPosPrintDatas == null) {
                    printFailure("暫不支持打印此單");
                    return;
                }
            } else {
                //獲取打印圖片
                listMap = printerInIt.getPrintBitmapByCount(mContext, defaultPrint);
                if (listMap != null) {
                    zoomBitmaps = listMap.get("");
                } else {
                    printFailure("打印失敗，生成打印數據失敗");
                    return;
                }
                if (zoomBitmaps == null) {
                    //打印失敗
                    printFailure("打印失敗，生成打印數據失敗");
                } else {
                    //保存打印圖片到本地
                    setPrinterBitmapToLocation(type, type, mOrderNo, listMap);
                }
            }
            if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_IP) {
                //IP打印
                printerInIt.ipDevicePrint(defaultPrint, zoomBitmaps);
            } else if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_LOCAL) {
                //本地N5或Sunmi打印
                printerInIt.locationPrint(zoomBitmaps, BBPosPrintDatas);
            } else if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_USB) {
                //USB打印打印
                printerInIt.usbPrint(mContext, zoomBitmaps);
            } else {
                printFailure("未找到對應的打印類型");
            }
        }
        LoganManager.w_code(TAG, "printByDevice end");
    }

    /**
     * 将所要打印的图片保存到本地
     */
    private void setPrinterBitmapToLocation(int orderType, int printType, String orderNo, Map<String, List<Bitmap>> bitmapMaps) {
        if (bitmapMaps.size() > 0 && bitmapMaps.get("") != null) {
            String prjName = orderNo + "-" + System.currentTimeMillis();
            PrinterFlowProxy.newInstance().dispatchPrinterBitmapBefore(orderType, printType, prjName, bitmapMaps.get(""));
        }
    }

    private void addPrintProgress(String printState) {
        runOnUiThread(() -> printerLoadingDialog.setTitle(printState));
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //doSomeTing，點擊當前頁面任意地方自動關閉
        killMyself();
        return true;
    }

    //
//    @Override
//    public void printStateChanged(int state) {
//        String tip = "加載中...";
//        switch (state) {
//            case PrintSocketHolder.STATE_1:
//                tip = "開始創建連接";
//                break;
//            case PrintSocketHolder.STATE_2:
//                tip = "創建連接成功，開始發送數據";
//                break;
//            case PrintSocketHolder.STATE_3:
//                tip = "開始寫入數據";
//                break;
//            case PrintSocketHolder.STATE_4://关闭输出流
//                tip = "關閉中";
//                killMyself();
//                break;
//            default:
//                break;
//        }
//        LoganManager.w_printer(TAG, "printStateChanged state--->" + tip);
//        addPrintProgress(tip);
//    }
//

    public void printSuccess() {
        LoganManager.w_printer(TAG, "printFailure 打印成功");
        killMyself();
        CC.sendCCResult(callId, CCResult.success());
    }

    public void printFailure(String msg) {
        PrinterFlowProxy.newInstance().dispatchPrintError(new Exception(msg), 0);
    }

    @Override
    public void initIntent() {

    }

    @Override
    public void initTopBar() {

    }

    @Override
    public void initLanguage() {

    }

    @Override
    public void initLayoutParams() {

    }

    @Override
    public void initLayoutVisible() {

    }

    @Override
    public void showLoading(String message) {

    }

    @Override
    public void hideLoading() {

    }

    @Override
    public void showMessage(@NonNull String message) {
        checkNotNull(message);
        ToastUtils.show(mContext, message);
    }

    @Override
    public void launchActivity(@NonNull Intent intent) {
        checkNotNull(intent);
        ArmsUtils.startActivity(intent);
    }

    @Override
    public void killMyself() {
//        if (printerResult) {
        finish();
//        }
    }

    @Override
    public void showPrinterList(List<PrinterDeviceBean> deviceBeans) {
//        printerDeviceBeans = deviceBeans;
//        printerInIt.print(printerDeviceBeans);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
//        if (requestCode == ADD_PRINT_CODE && resultCode == PrintActivity.ADD_PRINT_CODE) {
//            //添加打印機成功，
//            if (data != null && data.getSerializableExtra("printDevice") != null) {
//                List<PrinterDeviceBean> printerDeviceBeans = new ArrayList<>();
//                printerDeviceBeans.add((PrinterDeviceBean) data.getSerializableExtra("printDevice"));
//                printerInIt.print(printerDeviceBeans);
//            } else {
//                ToastUtils.show(mContext, "未獲取到打印機");
//                printFailure();
//            }
//        } else {
//            ToastUtils.show(mContext, "未獲取到打印機");
//            printFailure();
//        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (printerLoadingDialog != null) {
            printerLoadingDialog.dismiss();
            printerLoadingDialog = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //關閉打印頁面時，關閉所有打印連接
        //關閉ip打印連接
        PrintSocketHolder.getInstance().closeSocket();
        //關閉針式打印連接
        if (printerInIt != null) {
            printerInIt.disconnectEpson();
        }
        PrinterFlowProxy.newInstance().unregisterPrinterFlowListener(printerFlowListener);
    }

    @Override
    public void onResult(int errorCode) {
        //ip打印結果回調

    }
}
