package com.module.pay.nayax;

import android.os.Build;
import android.os.SystemClock;
import android.util.Log;

import com.bitmick.marshall.models.vmc_configuration;
import com.bitmick.marshall.vmc.vmc_framework;
import com.bitmick.marshall.vmc.vmc_general_t;
import com.bitmick.marshall.vmc.vmc_link;
import com.bitmick.marshall.vmc.vmc_socket_t;
import com.bitmick.marshall.vmc.vmc_vend_t;
import com.bitmick.utils.Utils;
import com.quyunshuo.androidbaseframemvvm.base.utils.SpUtils;
import com.quyunshuo.androidbaseframemvvm.common.constant.MMKVName;
import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.BufferedWriter;
import java.util.Timer;
import java.util.TimerTask;
public class CreditCardMain {
    private final static String TAG = "main_class"; //CreditCardMain.class.getSimpleName();

    private static vmc_framework m_vmc;
    private static vmc_configuration vmc_config;
    private static vmc_vend_t.vend_session_t m_session;
    private static boolean is_running;

    private static Timer m_session_timer;
    private static Timer m_vend_request_timer;

    private static String m_pp_number;


    //-----------------单例模式 start---------------
    private CreditCardMain() {
        m_vmc = vmc_framework.getInstance();
        vmc_config = new vmc_configuration();
        String plcserialport = SpUtils.INSTANCE.getString(MMKVName.Companion.getTTYS_NAYAX(), "ttyS1");
        vmc_config.port_vpos = "/dev/" + plcserialport;// /dev/ttymxc1
        vmc_config.port_vpos_baud = 115200;
        vmc_config.machine_type = vmc_configuration.machine_type_none;
        vmc_config.serial = "01234567";
        vmc_config.model = "sunzee";
        vmc_config.sw_ver = vmc_framework.get_version();//SDK版本信息
        vmc_config.multi_session_support = false;//是否多商品
        vmc_config.price_not_final_support = false;//不是最终价格
        vmc_config.reader_always_on = false;//默认接受刷卡
        vmc_config.always_idle = SpUtils.INSTANCE.getBoolean(MMKVName.Companion.getNAYAX_MODE(), false);//一直闲置。  //苹果支付，就是一直闲置true
        vmc_config.vend_denied_policy = vmc_configuration.vend_denied_policy_cancel;
        vmc_config.mifare_approved_by_vmc_support = false;
        vmc_config.mag_card_approved_by_vmc_support = false;
//        vmc_config.dump_packets_level = vmc_configuration.debug_level_dump_all;
        vmc_config.dump_packets_level = vmc_configuration.debug_level_dump_moderate;
        vmc_config.debug = true;//是否调试模式

        BufferedWriter out = null;


        android.util.Log.d(TAG, "CreditCardMain: ");

        m_vmc.link.set_lowlevel(new SerialTool());//实现lowlevel_i接口的串口工具
        m_vmc.link.configure(vmc_config);//设备配置
        m_vmc.link.set_events(new vmc_link_events());//连接事件
        m_vmc.vend.register_callbacks(new vmc_vend_events());//交易事件
        m_vmc.socket.register_callbacks(new vmc_socket_events());//Socket事件
//        m_vmc.general.setEvents(new vmc_greneral_events());//基础事件
        m_vmc.general.register_callbacks(new vmc_general_t.GeneralEvents() {
            @Override
            public void onDCSParamChange(int dcs_param, byte[] data) {
                com.bitmick.utils.Log.d(TAG, String.format("dcs(%d): %s", dcs_param, new String(data)));
            }

            @Override
            public void onTransferData(byte[] bytes) {
                com.bitmick.utils.Log.d("--->", String.format("received %d bytes in transfer data", bytes.length));
            }

            @Override
            public void onDisplayEventButtonPressed(byte button_id) {
                com.bitmick.utils.Log.d("--->", String.format("button pressed: %d", button_id));
            }

            @Override
            public void onDisplayEventTextInput(String input) {
                com.bitmick.utils.Log.d("--->", String.format("text input: %d", input));
            }

            @Override
            public void onTimeUpdate(byte b, byte b1, byte b2, byte b3, byte b4, byte b5) {

            }
        });

    }

    private static CreditCardMain sCreditCardMain;

    public static CreditCardMain getCreditCardMain() {
        if (sCreditCardMain == null) {
            synchronized (CreditCardContract.class) {
                if (sCreditCardMain == null) {
                    sCreditCardMain = new CreditCardMain();
                }
            }
        }
        return sCreditCardMain;
    }
    //-----------------单例模式 end---------------

    //////////////////////////////////////////////////////////////////////////////////////////////
    // function name:
    // input:
    // output:
    // notes:
    /////////////////////////////////////////////////////////////////////////////////////////////
    public class WaitForCreditCardTimerTask extends TimerTask {
        //刷卡等待时长。
        private final static int TIMEOUT_MS = 120000;
        private final String TAG = WaitForCreditCardTimerTask.class.getSimpleName();

        private long start_time;

        public WaitForCreditCardTimerTask() {
            start_time = Utils.currentTimeMillis();
            Log.d(TAG, String.format("starting session timer. you have %d seconds to swipe card before timeout", TIMEOUT_MS / 1000));
        }

        @Override
        public void run() {
            long ms = Utils.currentTimeMillis();

            if (ms - start_time > TIMEOUT_MS) {
                // stop session, no credit card arrived yet
                m_vmc.vend.session_cancel();

                // stop session timer
                session_timer_stop();
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////
    // function name:
    // input:
    // output:
    // notes:
    /////////////////////////////////////////////////////////////////////////////////////////////
    private void session_timer_start() {
        // invoke keep-alive - timer
        if (m_session_timer == null) {
            m_session_timer = new Timer(true);
            m_session_timer.scheduleAtFixedRate(new WaitForCreditCardTimerTask(), 0, 1000);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////
    // function name:
    // input:
    // output:
    // notes:
    /////////////////////////////////////////////////////////////////////////////////////////////
    private void session_timer_stop() {
        // stop keepalive timer
        if (m_session_timer != null) {
            m_session_timer.cancel();
            m_session_timer = null;
        }
    }

    //串口通信并且开始等待刷卡
    public void StartCommunication(int i) {
        XLogUtil.INSTANCE.d("StartCommunication: 开始信用卡支付了1");
        addMsg(i + "StartCommunication:" + m_vmc);
        if (m_vmc!=null) {
            m_vmc.start();//打开连接

        }
    }
    //串口通信并且开始等待刷卡
    public void stopCommunication(int i) {
        m_vmc.stop();//关闭连接
    }

    //是否联机、配对，串口通信成功
    public boolean is_ready() {
        return m_vmc.link.is_ready();
    }

    public boolean is_read1() {
        if (m_vmc != null) {
            return m_vmc.vend.is_ready();
        }
        return false;
    }

    //开始刷卡
    public void startThreadTimer() {
        SystemClock.sleep(100);
        session_timer_stop();//示例里面是没有的
        session_timer_start();
        m_vmc.vend.session_start(vmc_vend_t.session_type_credit_e);
    }

    //结束串口通信
    public void StopPay() {
        m_vmc.link.stop();
    }

    //取消本次操作
    public void CanselSession() {
        SystemClock.sleep(100);
        session_timer_stop();
        m_vmc.vend.session_cancel();

    }

    /**
     * 发送cash sale
     *
     * @param code
     * @param price
     */
    public void cashSale(int code, int price) {
        m_vmc.vend.vend_cash_sale(new vmc_vend_t.cash_sale_t(code, price));
    }

    //取消本次操作后，结束关闭一下
    public void CloseSession() {
        if (m_session != null)
            m_vmc.vend.session_close(m_session);
    }

    /**
     * *
     * * 连接事件
     */

    private class vmc_link_events implements vmc_link.vmc_link_events_t {

        @Override
        public void onReady(vmc_link.vpos_config_t config) {
            m_vmc.general.alert((short) 0x01, "hello there");
            addMsg("onReady hello there");
        }

        @Override
        public void onCommError() {
            XLogUtil.INSTANCE.d("vmc_link_events.onCommError通讯错误");
            addMsg("vmc_link_events.onCommError通讯错误");
        }

    }


    /**
     * *
     * * 交易事件
     */
    private class vmc_vend_events implements vmc_vend_t.vend_callbacks_t {

        @Override
        public void onReady(vmc_vend_t.vend_session_t session) {
            addMsg("vmc_vend_events.onReady session_status:");
        }

        @Override
        public void onStatus(int status) {
            addMsg(String.format("received status: %d10", status));
            com.bitmick.utils.Log.d(TAG, String.format("received status: %d10", status));
        }

        @Override
        public void onSessionBegin(int funds_avail) {

            addMsg("vmc_vend_events.onSessionBegin:" + Thread.currentThread().getName());
            //信用卡已被检测到。停止计时器
            session_timer_stop();
            vendRequest();
        }

        @Override
        public void onTransactionInfo(vmc_vend_t.vend_session_data_t data) {
            if (data.cc_last_4_digits != null) {
                addMsg(String.format("received cc last 4 digits: %s", data.cc_last_4_digits));
            }

            if (data.transaction_id != -1) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    addMsg(Long.toUnsignedString(m_vmc.vend.get_transaction_id()));
                }
            }

            if (data.card_bin != null) {
                addMsg(String.format("card bin: %s", data.card_bin));

                m_pp_number = data.card_bin;
            }

            if (data.prop_card_uid != null) {

                addMsg(String.format("prop card uid: %s", data.prop_card_uid));
            }
        }

        //这一步就已经确定了钱够了，可以开始做糖了。但是还没扣钱。
        //返回true说明成功，返回false标明不扣钱。
        @Override
        public boolean onVendApproved(vmc_vend_t.vend_session_t session) {
            int index = 40;
            addMsg("vmc_vend_events.onVendApproved");
            addMsg("交易成功");
            //让机器做糖
            EventBus.getDefault().post(new CreditCardMessage(CreditCardMessage.Type.success));
            //如果在取棍子？怎么办。给他40秒的时间，如果不行就回退钱。
//            SystemClock.sleep(5000);//休息5秒，我们开始判断是否跳转到制作中，如果没有跳转，我们就放回错误
//            //如果上一次结束了，也就是客户支付成功，但是还保留在支付界面，怎么办呢？不扣。，但是会积累下去。问题也不大。
//            for (int i = 0;i <= index; i++){
//                SystemClock.sleep(1000);
//                if (Global.isInProduction) {//如果跳转了，那么就支付成功
//                    Global.isInProduction = false;
//                    return true;
//                }
//            }
//            return false;//如果没有跳转，就是失败了。
            return true;
//            SystemClock.sleep(50000);
//            //LogUtil.d(TAG, "如果为0，说明是在制作中" + Global.isDoSugar);
//            //如果为0，说明是在制作中
//            for (int i = 0; Global.isDoSugar == 0; i++) {
////            while (Global.isDoSugar == 0) {
//                SystemClock.sleep(2000);
//                //  前面已经过了50，还有90到三分钟，45次的时候就手动结束
////                mTime++;
//                if (i == 95) {//这一步存在太多问题，比如温湿度不到达怎么办呢？插棍太久怎么办呢？【这一步不需要】
////                    //LogUtil.d(TAG, "前面已经过了50，还有90到三分钟，45次的时候就手动结束" + mTime);
////                    //发生这种情况，会退款，但是机器不会恢复到原来的界面，还是在应该在的界面。
//                    return false;
//                }
//            }
//            //如果为1，说明已经成功
//            if (Global.isDoSugar == 1) {
//                //LogUtil.d(TAG, "如果为1，说明已经成功" + mTime);
//                return true;
//            }
//            //如果不为1不为0，说明失败。
//            //LogUtil.d(TAG, "如果不为1，说明失败" + mTime);
//            return false;
//            return true;
        }

        //余额不足的情况，会调用这个回调
        @Override
        public void onVendDenied(vmc_vend_t.vend_session_t session) {
            addMsg("vmc_vend_events.onVendDenied");
            addMsg("交易失败");
            XLogUtil.INSTANCE.d("onVendDenied session == " + session.session_status);
            //按键取消了。
            //资金不足或支付介质/账户错误
            //1.这里弹出一个提示，并且关闭本次会话。【资金不足/无效卡，两秒消失。】
            //EventBus.getDefault().post(new CreditCardMessage(CreditCardMessage.Type.success));
            XLogUtil.INSTANCE.d("Amit取消了");
            //重新等待刷卡。
//            startThreadTimer();
            EventBus.getDefault().post(new CreditCardMessage(CreditCardMessage.Type.invalid));
        }

        @Override
        public void onSettlement(boolean success) {
            addMsg("vmc_vend_events.onSettlement");
            addMsg(String.format("settlement: {0}", success ? "success" : "fail"));
        }
    }

    /**
     * 手动发起支付
     */
    public void vendRequest() {
        int code = Constant.getCommodity_code();
        int quantity = Constant.getCommodity_quantity();
        int price = (int) Constant.getCommodity_price();
        m_session = new vmc_vend_t.vend_session_t(code, 1, (byte) 0, price);
        // vend request
        m_vmc.vend.vend_request(m_session);
        // example: approve mifar/mag card externally (vmc authenticates)
        if (vmc_config.mag_card_approved_by_vmc_support || vmc_config.mifare_approved_by_vmc_support) {
            m_vmc.vend.client_gateway_auth(true);
        }
    }

    private static class vmc_socket_events implements vmc_socket_t.socket_callbacks_t {

        long start_time_stamp;
        int received_bytes = 0;

        @Override
        public void onReady() {
            addMsg("vmc_socket_events.onReady");
        }

        @Override
        public void onSocketOpened() {
            start_time_stamp = System.currentTimeMillis();
            addMsg("vmc_socket_events.onSocketOpened");
        }

        @Override
        public void onSocketClosed() {
            addMsg("vmc_socket_events.onSocketClosed");
        }

        @Override
        public void onSocketError() {
            XLogUtil.INSTANCE.d( "vmc_link_events.onSocketError套接字错误");
            addMsg("vmc_link_events.onSocketError套接字错误");
        }

        @Override
        public void onTimerTick(long ms) {
        }

        @Override
        public void onTransmitDone(boolean success) {
            addMsg("vmc_socket_events.onTransmitDone");
        }

        @Override
        public boolean onReceive(byte[] buffer, int size) {
            received_bytes += size;

            com.bitmick.utils.Log.d("--->", String.format("received: %d bytes, total: %d", size, received_bytes));
            addMsg("vmc_socket_events.onReceive");
            return true;
        }

        @Override
        public void onFTPDone(boolean success) {
            long total_dl_time = System.currentTimeMillis() - start_time_stamp;
            com.bitmick.utils.Log.d("--->", String.format("ftp done. total: %d bytes. throughput = %f kb/sec", received_bytes, ((float) received_bytes) / total_dl_time));
            addMsg("vmc_socket_events.onFTPDone");
            received_bytes = 0;
        }
    }

    /**
     * 添加显示的消息
     *
     * @param str
     */
    private static void addMsg(String str) {
        XLogUtil.INSTANCE.d("NAYAX-DEMO:" + str + ":::::::" + Thread.currentThread().getName());
        android.util.Log.d(TAG, "addMsg: " + str + ":::::::" + Thread.currentThread().getName());
    }
}