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

import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

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.app.GsaCloudApplication;
import com.gingersoft.gsa.cloud.common.constans.PrintConstans;
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.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.ui.utils.DialogUtils;
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.OpenCashBoxMaker;
import com.joe.print.mvp.print.PrintInstruction;
import com.joe.print.mvp.print.PrintListener;
import com.joe.print.mvp.print.PrintPrjKitchen;
import com.joe.print.mvp.print.PrinterRoot;
import com.joe.print.mvp.print.utils.MyPrintUtils;
import com.joe.print.mvp.ui.adapter.DialogPrinterListAdapter;
import com.joe.print.mvp.ui.adapter.PrintProgressAdapter;
import com.yanzhenjie.recyclerview.widget.DefaultItemDecoration;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;

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, DialogInterface.OnDismissListener, PrintListener, PrintSocketHolder.OnStateChangedListener, PrintExecutor.OnPrintResultListener {

    public final static int ADD_PRINT_CODE = 1001;//添加打印機回調
    public final static int DIMISS_LOADING = 1002;//關閉加載窗
    public final static int FINISH = 1003;//關閉頁面
    public final static int ADD_PRINT_DEVICE = 1004;//添加打印機
    public final static int LACK_OF_PAPER = 1005;//缺紙


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

    private Dialog mLoadingDialog;
    private TextView mTvLoadingTip;
    /**
     * 0：上菜紙
     * 1：印單
     * 2：結賬單
     * 3：廚房單
     * 4：打印view
     * 5：打印外賣接單
     * 6：其他指令
     */
    private int type;
    //是否顯示打印等待彈窗
    private boolean isShowDialog;

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

    @Override
    public int initView(@Nullable Bundle savedInstanceState) {
        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 initData(@Nullable Bundle savedInstanceState) {
        callId = CCUtil.getNavigateCallId(this);

        //獲取打印類型，根據打印類型生成對應的bitmap
        type = CCUtil.getNavigateParam(this, PrintConstans.PRINT_TYPE, PrintConstans.PRINT_TEST);
        PrintContent printContent = CCUtil.getNavigateParam(this, PrintConstans.PRINT_CONTENT, null);
        isShowDialog = CCUtil.getNavigateParam(this, PrintConstans.PRINT_LOADING, true);

        printerInIt = PrinterRoot.getPrinterByType(type, printContent);
        if (printerInIt != null) {
            printerInIt.setPrintListener(this);
        }
        initPrintConfig();
    }

    private int selectPrint = -1;

    private void initPrintConfig() {
        PrintCurrencyBean printCurrencyBean;
        PrinterDeviceBean defaultPrint;
        //獲取通用打印配置，不同的打印
        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);
        }
        //獲取打印機列表
        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) {
            List<PrjBean.DataBean.Bean> printDatas = CCUtil.getNavigateParam(this, "prjBeans", null);
            Map<String, List<PrjBean.DataBean.Bean>> prjMap = PrintPrjKitchen.getPrjMap();
            String printLocation = null;
            for (PrjBean.DataBean.Bean prjBean : printDatas) {
                if (printLocation == null) {
                    if (TextUtil.isNotEmptyOrNullOrUndefined(prjBean.getPrintPosition())) {
                        printLocation = prjBean.getPrintPosition();
                        defaultPrint = mPresenter.getPrinterDeviceBeanByName(printerDeviceBeans, printLocation);
                        if (defaultPrint == null) {
                            printFailure("未找到對應的打印機");
                            return;
                        }
                    } else {
                        if (defaultPrint == null) {
                            printLocation = "";
                        } else {
                            printLocation = defaultPrint.getName();
                        }
                    }
                }
                prjBean.setPrintPosition(printLocation);
                prjBean.setCurrentIndex(1);
            }
            prjMap.put("", printDatas);
        }

        if (defaultPrint == null) {
            //沒有默認打印機，查看當前餐廳有沒有打印機
            //如果當前餐廳有打印機，彈出彈窗讓用戶選擇一個打印機打印
            if (printerDeviceBeans != null && printerDeviceBeans.size() > 0) {
                PrintCurrencyBean finalPrintCurrencyBean = printCurrencyBean;
                new DialogUtils(mContext, R.layout.print_dialog_internet_list) {
                    @Override
                    public void initLayout(ViewHepler hepler, Dialog dialog) {
                        RecyclerView mRvPrintList = hepler.getView(R.id.rv_print_list);
                        DialogPrinterListAdapter printListAdapter = new DialogPrinterListAdapter(printerDeviceBeans, mContext);
                        mRvPrintList.setLayoutManager(new LinearLayoutManager(mContext));
                        //分割线
                        mRvPrintList.addItemDecoration(new DefaultItemDecoration(ContextCompat.getColor(mContext, R.color.line_color)));
                        mRvPrintList.setAdapter(printListAdapter);
                        printListAdapter.setOnItemClickListener((adapter, view, position) -> {
                            //用戶選擇的ip打印機打印
                            PrinterDeviceBean defaultPrint = MyPrintUtils.configPrinterProperties(finalPrintCurrencyBean, printerDeviceBeans.get(position));
                            printByDevice(defaultPrint);
                            selectPrint = position;
                            SPUtils.put("defaultPrint", printerDeviceBeans.get(position).getName());
                            dialog.dismiss();
                        });
                    }
                }
                        .setHeight(ArmsUtils.getScreenHeidth(mContext) / 2)
                        .setWidth((int) (ArmsUtils.getScreenWidth(mContext) * 0.8))
                        .setOnDismissListener(dialog -> {
                            if (selectPrint == -1) {
                                printFailure("未選擇打印機");
                            }
                        })
                        .show();
            } else {
                //沒有打印機
                ToastUtils.show(mContext, "沒有打印機，請先添加打印機");
            }
        } else {
            defaultPrint = MyPrintUtils.configPrinterProperties(printCurrencyBean, defaultPrint);
            printByDevice(defaultPrint);
        }
    }


    //打印邏輯，獲取對應的打印配置--打印機或是通用配置
    //根據配置生成配置好的圖片----生成圖片邏輯：把打印的單分為幾個模塊，再由不同的單拼接出對應的單，(如果是針式，生成對應的文字)
    //再獲取打印方式(IP、本機、USB、藍牙或其他的)，調用打印
    private void printByDevice(PrinterDeviceBean defaultPrint) {
        //獲取對應的打印類
        if (printerInIt instanceof PrintInstruction) {
            //開錢箱
            PrintExecutor executor = new PrintExecutor(defaultPrint);
            executor.doPrinterRequestAsync(new OpenCashBoxMaker());
        } else {
            if (isShowDialog) {
                initDialog();
            }
            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 && zoomBitmaps.size() > 0) {

                } else {
                    //打印失敗
                    printFailure("打印失敗，生成打印數據失敗");
                }
            }
            //獲得對應的圖片
            if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_IP) {
                //IP打印
                printerInIt.ipDevicePrint(defaultPrint, zoomBitmaps);
            } else if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_LOCAL) {
                //本地N5或Sunmi打印
                printerInIt.locationPrint(zoomBitmaps, BBPosPrintDatas, this);
            } else if (defaultPrint.getPrinterDeviceType() == PrinterDeviceBean.PRINT_USB) {
                //USB打印打印
                printerInIt.usbPrint(mContext, zoomBitmaps);
            }
//            else if (defaultPrint.getPrinterDeviceType() == 4) {
//                printerInIt.transmitPrjToPc(defaultPrint);
//            }
            else {
                printFailure("未找到對應的打印類型");
            }

        }
    }

    private Map<String, List<PrjBean.DataBean.Bean>> setPrjIndex(Map<String, List<PrjBean.DataBean.Bean>> listMap, int totalPrj) {
        int currentIndex = 0;
        for (Map.Entry<String, List<PrjBean.DataBean.Bean>> prjMap : listMap.entrySet()) {
            for (PrjBean.DataBean.Bean bean : prjMap.getValue()) {
                bean.setTotalPrj(totalPrj);
                if (bean.getStatus() == 2) {
                    currentIndex++;
                } else {
                    if (currentIndex == 0) {
                        currentIndex = 1;
                    }
                }
                bean.setCurrentIndex(currentIndex);
            }
            currentIndex++;
        }
        return listMap;
    }

    private Map<String, List<PrjBean.DataBean.Bean>> printDataToMap(List<PrjBean.DataBean.Bean> printData) {
        Map<String, List<PrjBean.DataBean.Bean>> map = new HashMap<>();
        PrinterDeviceBean defaultPainter = null;
        //獲得默認的打印機
        for (PrinterDeviceBean printerDeviceBean : printerDeviceBeans) {
            if (printerDeviceBean.getType() == 2) {
                defaultPainter = printerDeviceBean;
                break;
            }
        }

        //將prj集合通過打印位置轉成map
        for (PrjBean.DataBean.Bean bean : printData) {
            if (TextUtil.isNotEmptyOrNullOrUndefined(bean.getPrintPosition())) {
                List<PrjBean.DataBean.Bean> mapByKey = map.get(bean.getPrintPosition());
                if (mapByKey != null) {
                    mapByKey.add(bean);
                } else {
                    map.put(bean.getPrintPosition(), Collections.singletonList(bean));
                }
            } else if (defaultPainter != null) {
                //沒有打印位置的，由默認的位置去打印
                bean.setPrintPosition(defaultPainter.getName());
                List<PrjBean.DataBean.Bean> mapByKey = map.get(bean.getPrintPosition());
                if (mapByKey != null) {
                    mapByKey.add(bean);
                } else {
                    map.put(bean.getPrintPosition(), Collections.singletonList(bean));
                }
            } else {
                ToastUtils.show(this, "未配置打印機");
            }
        }
        return map;
    }

    private PrintProgressAdapter adapter;

    private void setPrintProgress(int state) {
        if (adapter != null) {
            adapter.setProgress(state);
        }
    }

    private void initDialog() {
        try {
//            new DialogUtils(this, R.layout.print_layout_print_progress) {
//                @Override
//                public void initLayout(ViewHepler hepler, Dialog dialog) {
//                    List<String> stauts = Arrays.asList("生成數據中", "連接打印機", "開始寫入數據", "打印成功");
//                    adapter = new PrintProgressAdapter(stauts);
//                    hepler.setAdapter(R.id.rv_print_progress, new LinearLayoutManager(mContext), adapter);
//                }
//            }.setWidth((int) (DeviceUtils.getScreenWidth(mContext) * 0.8))
//                    .show();
            View view = LayoutInflater.from(mContext).inflate(R.layout.ui_dialog_loading, null);
            mTvLoadingTip = view.findViewById(R.id.tv_loading_dialog_text);
            mLoadingDialog = new Dialog(this, R.style.ui_loading_dialog);
            mLoadingDialog.setCancelable(true);
            mLoadingDialog.setCanceledOnTouchOutside(false);
            Window window = mLoadingDialog.getWindow();
            window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            mLoadingDialog.setContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
            if (!this.isFinishing()) {
                mLoadingDialog.show();
                setLoadingText("加載中...");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setLoadingText(String tip) {
        Observable.just(1)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(integer -> {
                    if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
                        mTvLoadingTip.setText(tip);
                    }
                });
    }

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

    @Override
    public void printStateChanged(int state) {
        String tip = "加載中...";
        switch (state) {
            case PrintSocketHolder.ERROR_0:
                tip = "打印成功";
                setPrintProgress(3);
                break;
            case PrintSocketHolder.ERROR_1:
                tip = "生成打印數據失敗";
                break;
            case PrintSocketHolder.ERROR_2:
            case PrintSocketHolder.ERROR_3:
                tip = "連接打印機失敗";
                break;
            case PrintSocketHolder.ERROR_4:
                tip = "寫入測試頁面數據失敗";
                break;
            case PrintSocketHolder.ERROR_5:
                tip = "必要的參數不能為空";
                break;
            case PrintSocketHolder.STATE_0:
                setPrintProgress(0);
                break;
            case PrintSocketHolder.STATE_1:
                tip = "開始創建連接";
                break;
            case PrintSocketHolder.STATE_2:
                tip = "創建連接成功，開始發送數據";
                setPrintProgress(1);
                break;
            case PrintSocketHolder.STATE_3:
                tip = "開始寫入數據";
                setPrintProgress(2);
                break;
            case PrintSocketHolder.STATE_4:
                tip = "關閉中";
                finish();
                break;
            case DIMISS_LOADING:
                disLoadingDialog();
                break;
            case FINISH:
                finish();
                break;
            case ADD_PRINT_DEVICE:
                addPrintDevice();
                break;
            case LACK_OF_PAPER:
                //缺紙
                printFailure("打印機缺紙");
                break;
        }
        setLoadingText(tip);
    }

    /**
     * 打印成功
     */
    @Override
    public void printSuccess() {
//        if (printCount <= 1) {
        CC.sendCCResult(callId, CCResult.success());
        disLoadingDialog();
        finish();
//        finish();
//        } else {
//            printCount--;
//        }
    }

    @Override
    public void printFailure(String msg) {
        if (!TextUtil.isEmptyOrNullOrUndefined(msg)) {
            ToastUtils.show(GsaCloudApplication.getAppContext(), msg);
            CC.sendCCResult(callId, CCResult.error(msg));
        }else {
            CC.sendCCResult(callId, CCResult.error("print error"));
        }
//        if (printCount <= 1) {
        finish();
//        } else {
//            printCount--;
//        }
    }

    @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() {
        finish();
    }

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

    private void addPrintDevice() {
        printFailure("沒有打印機，請添加");
//        startActivityForResult(new Intent(mContext, PrinterAddActivity.class), ADD_PRINT_CODE);
    }

    @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
    public void onDismiss(DialogInterface dialog) {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        disLoadingDialog();
    }

    private void disLoadingDialog() {
        Observable.just(1)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(integer -> {
                    if (mLoadingDialog != null) {
                        mLoadingDialog.dismiss();
                        mLoadingDialog = null;
                    }
                });
    }

    @Override
    public void onStateChanged(int state, PrinterDeviceBean printerDeviceBean) {
        //ip打印狀態修改回調

    }

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

    }
}
