package com.genlot.ninglottery.game.common;

import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.blankj.utilcode.util.ScreenUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.genlot.nativesdk.SystemNI;
import com.genlot.nativesdk.model.GameRuntimeAttr;
import com.genlot.nativesdk.model.GameTicket;
import com.genlot.ninglottery.R;
import com.genlot.ninglottery.application.LotteryApplication;
import com.genlot.ninglottery.base.BaseMVPFragment;
import com.genlot.ninglottery.event.BetChangeEvent;
import com.genlot.ninglottery.game.GameActivity;
import com.genlot.ninglottery.game.GameManager;
import com.genlot.ninglottery.game.GamePresenter;
import com.genlot.ninglottery.game.IGameView;
import com.genlot.ninglottery.game.bet.BetManager;
import com.genlot.ninglottery.game.bet.BetView;
import com.genlot.ninglottery.game.bet.IBetBean;
import com.genlot.ninglottery.game.d3.bean.ZuXuan;
import com.genlot.ninglottery.game.k3.bean.SingleK3;
import com.genlot.ninglottery.game.ssq.bean.BaseSSQ;
import com.genlot.ninglottery.model.PlayTypeID;
import com.genlot.ninglottery.toolkit.GameUtil;
import com.genlot.ninglottery.toolkit.LogTool;
import com.genlot.ninglottery.toolkit.PrinterTool;
import com.genlot.ninglottery.toolkit.StringTool;
import com.genlot.ninglottery.toolkit.TrainMode;
import com.genlot.ninglottery.widget.Diaolog.CommonDialog;
import com.genlot.ninglottery.widget.Diaolog.ViewConvertListener;
import com.genlot.ninglottery.widget.KeyboardEditText;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.Arrays;
import java.util.Calendar;

import butterknife.BindView;
import butterknife.OnClick;

/**
 * @author ZhuYongKang
 * @description 游戏公共Fragment定义
 * @date 2019/8/23
 */
public abstract class CommonFragment extends BaseMVPFragment implements IGameView {

    public GamePresenter mPresenter;
    /**
     * 机选注数或者机选位数
     */
    public int mRandomNum;

    /**
     * 出票注数
     */
    private int mOutNum;
    /**
     * 剩余注数
     */
    private int mLeftNum;
    /**
     * 是否是机选状态
     */
    public boolean isRandom = false;

    private boolean isSingleOver5 = false;

    /**
     * 是否复制
     */
    public boolean isFromCopy;

    public int mPlayType;
    public BetView mBetView;

    @Override
    public void onCreateViewFinished(Bundle state) {
        mPresenter = new GamePresenter();
        mPresenter.attachView(this);
        isFromCopy = false;
        initData();
        initAdapter();
        EventBus.getDefault().register(this);
        initViews();
        tvMulti.setOnTextFinishListener(value -> {
            if (TextUtils.isEmpty(value)) {
                tvMulti.setText("1");
            }
            tvMulti.clearFocus();
            int time = Integer.parseInt(tvMulti.getText().toString().trim());
            if (time == 0) {
                ToastUtils.showShort("倍数最小为1");
                tvMulti.setText("1");
            }
            if (time > getMaxTimes()) {
                ToastUtils.showShort("最大倍数为" + getMaxTimes() + "倍");
                tvMulti.setText(String.valueOf(getMaxTimes()));
            }
            BetManager.getInstance().setTimes(Integer.parseInt(tvMulti.getText().toString().trim()));
            refreshMoney();
        });
    }

    public abstract void initData();

    public abstract void initAdapter();

    public abstract void initViews();

    @Override
    public void onResume() {
        super.onResume();
        //是否需要冲正
        GameTicket ticket = GameManager.getLastTicket();
        if (ticket.mGameID > 0) {
            showReverseDialog(ticket);
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        EventBus.getDefault().unregister(this);
        mPresenter.detachView();
        mPresenter = null;
    }

    /**
     * 最大倍数
     * @return  int
     */
    public abstract int getMaxTimes();
    /**
     * 单注金额
     * @return  int
     */
    public abstract int getOneBetMoney();
    /**
     * 有效注数
     * @return  long
     */
    public abstract long getValidBets();

    public abstract void refreshAdapter(IBetBean betBean);

    public abstract void clearAdapter();

    public abstract void changePlayType(int playTypeId);

    @OnClick(R.id.bt_random)
    public abstract void random();

    /**
     * 机选
     *
     * @param num 注数
     */
    public void randomNum(int num){
        if (num >= 5) {
            num = 5;
        }
        for (int i = 0; i < num; i++) {
            IBetBean bean = mBetView.mBetList.get(i);
            bean.random();
            ((SingleView) mBetView).refreshRow(i);
            if (i == mBetView.mCurrentRow) {
                refreshAdapter(bean);
            }
        }
        refreshMoney();
    }

    /**
     * 改变号码界面和金额
     * @param event BetChangeEvent
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onBetChange(BetChangeEvent event) {
        IBetBean betBean = event.getIBetBean();
        LogTool.logD("onBetChange");
        refreshAdapter(betBean);
        refreshMoney();
    }

    /**
     * 复制成功
     * @param ticket GameTicket
     */
    public void onCopySuccess(GameTicket ticket) {
        LogTool.logD("onCopySuccess");
        isFromCopy = true;
        changePlayType(GameUtil.getPlayType(ticket.mPlayType, ticket.mBets));
        mBetView.parseBetData(ticket.gameBetDataString);
        refreshAdapter(mBetView.mBetList.get(0));
        tvMulti.setText(String.valueOf(ticket.mMultiTimes[0]));
        BetManager.getInstance().setTimes(ticket.mMultiTimes[0]);
        refreshMoney();
    }

    /**
     * 清空界面
     */
    public void clearUI(){
        tvMulti.setText("1");
        BetManager.getInstance().setTimes(1);
        BetManager.getInstance().setIssues(1);
        clearAdapter();
        if (mBetView != null) {
            mBetView.clear();
        }
        refreshMoney();
    }


    /**
     * 刷新投注金额
     */
    public void refreshMoney() {
        long money = getOneBetMoney() * getValidBets() *
                BetManager.getInstance().getTimes() * BetManager.getInstance().getIssues();
        tvSum.setText(StringTool.format1(money));
        tvSumTotal.setText(StringTool.format1(BetManager.getInstance().mTotalSum));
    }

    /**
     * 清空机选状态
     */
    public void clearRandom() {
        mRandomNum = 0;
        mOutNum = 0;
        mLeftNum = 0;
        isRandom = false;
        isSingleOver5 = false;
        showTips("");
    }

    @OnClick(R.id.bt_clear_all)
    public void clearAll() {
        BetManager.getInstance().mTotalSum = 0;
        clearUI();
        clearRandom();
    }

    @OnClick(R.id.bt_ticket_out)
    public void ticketOut() {
        if ("9".equals(GameManager.getUser())) {
            showTips("工号9操作员不能打票");
            return;
        }
        if (!PrinterTool.isPrintOK(activity)) {
            showTips("打印机状态异常，请检查...");
            return;
        }
        if (getValidBets() <= 0) {
            showTips("选择号码不正确");
            return;
        }
        showTicketOutDialog();
    }

    public void showTicketOutDialog() {
        String money = tvSum.getText().toString().trim();
        Spanned spanned = Html.fromHtml("本张彩票金额:" + "<font color='#ff0000'>" + money + "</font>" +
                "元" + "<br />"
                + "请确认是否出票!");
        CommonDialog.newInstance().setLayoutId(R.layout.dialog_ticket_out)
                .setConvertListener((ViewConvertListener) (holder, dialog) -> {
                    holder.setText(R.id.tv_content,spanned);
                    holder.setOnClickListener(R.id.bt_cancel, v -> dialog.dismiss());
                    holder.setOnClickListener(R.id.bt_confirm, v -> {
                        if (GameManager.isTrainMode) {
                            GameTicket ticket = getTrainModeTicket(money);
                            ticket.mVerifyCode = SystemNI.verifyCode(ticket);
                            PrinterTool.printTicket(LotteryApplication.getInstance(), ticket);
                            onBetSuccess(ticket.mBettingMoney, ticket.mBets);
                            dialog.dismiss();
                            return;
                        }
                        if (Double.parseDouble(money) > SystemNI.getProtectMoney()) {
                            showProtectMoneyDialog(money);
                            dialog.dismiss();
                            return;
                        }
                        GameTicket ticket = getGameTicket(money);
                        if (ticket == null) {
                            showTips("游戏状态不正确");
                            dialog.dismiss();
                            return;
                        }
                        mPresenter.t101200Bet(ticket);
                        dialog.dismiss();
                    });
                })
                .setSize(430, 270)
                .setOutCancel(false)
                .show(activity.getSupportFragmentManager());
    }

    /**
     * 显示单票保护对话框
     * @param money   金额
     */
    private void showProtectMoneyDialog(String money) {
        CommonDialog.newInstance().setLayoutId(R.layout.dialog_admin_login)
                .setConvertListener((ViewConvertListener) (holder, dialog) -> {
                    holder.setText(R.id.textView2,"操作员密码");
                    holder.setText(R.id.bt_setting,"确定");
                    EditText etPassword = holder.getView(R.id.et_admin_password);
                    holder.setOnClickListener(R.id.bt_no, v -> dialog.dismiss());
                    holder.setOnClickListener(R.id.bt_setting, v -> {
                        String password = etPassword.getText().toString().trim();
                        if (!GameManager.getPassword().equals(password)) {
                            dialog.dismiss();
                            showTips("操作员密码不正确!");
                            return;
                        }
                        GameTicket ticket = getGameTicket(money);
                        if (ticket == null) {
                            showTips("游戏状态不正确");
                            dialog.dismiss();
                            return;
                        }
                        mPresenter.t101200Bet(ticket);
                        dialog.dismiss();
                    });
                })
                .setSize(ScreenUtils.getScreenWidth(),ScreenUtils.getScreenHeight())
                .setOutCancel(false)
                .show(activity.getSupportFragmentManager());
    }

    /**
     * 显示冲正对话框
     * @param ticket   GameTicket
     */
    private void showReverseDialog(GameTicket ticket) {
        CommonDialog.newInstance().setLayoutId(R.layout.dialog_ticket_out)
                .setConvertListener((ViewConvertListener) (holder, dialog) -> {
                    holder.setText(R.id.textView7,"上张票异常");
                    holder.setText(R.id.tv_content,"是否进行冲正?");
                    holder.setOnClickListener(R.id.bt_cancel, v -> dialog.dismiss());
                    holder.setOnClickListener(R.id.bt_confirm, v -> {
                        mPresenter.t101999SpecialCancel(ticket);
                        dialog.dismiss();
                    });
                })
                .setOutCancel(false)
                .setSize(430, 270)
                .show(activity.getSupportFragmentManager());
    }

    /**
     * 生成投注票
     * @return  GameTicket
     */
    private GameTicket getGameTicket(String money) {
        int gameId = BetManager.getInstance().getGameId();
        GameRuntimeAttr attr = GameManager.getGameRuntime(gameId);
        if (attr == null) {
            return null;
        }
        GameTicket ticket = new GameTicket();
        ticket.mGameID = gameId;
        ticket.mGameIssue = attr.mGameIssue;
        ticket.mTicketSN = attr.mGameSN + 1;
        ticket.mBettingMoney = Double.parseDouble(money);
        ticket.mFeatureKey = GameUtil.randomN(0, 254);
        ticket.mTerminalID = SystemNI.getTerminalID();
        //mFeatureCode由mGameID mGameIssue mTicketSN mTerminalID mFeatureKey计算生成
        ticket.mFeatureCode = SystemNI.featureCode(ticket);
        ticket.mMultiIssue = BetManager.getInstance().getIssues();
        ticket.mMemberID = "0";
        String[] betData = mBetView.getBetData();
        LogTool.logD(Arrays.toString(betData));
        ticket.mBets = betData.length;
        for (int i = 0; i < betData.length; i++) {
            //手持终端投注暂时定位1
            ticket.mBettingMode[i] = 1;
            switch (BetManager.getInstance().getPlayType()) {
                case PlayTypeID.D3_ZUXUAN:
                    ticket.mPlayType[i] = ((ZuXuan) mBetView.mBetList.get(i)).getPlayTypeID(0);
                    break;
                case PlayTypeID.D3_PACK:
                    ticket.mPlayType[i] = ((ZuXuan) mBetView.mBetList.get(i)).getPlayTypeID(1);
                    break;
                case PlayTypeID.SSQ_BASE:
                case PlayTypeID.SSQ_BASE_MULTI:
                    ticket.mPlayType[i] = ((BaseSSQ) mBetView.mBetList.get(0)).getPlayTypeID();
                    break;
                case PlayTypeID.K3_SINGLE:
                    ticket.mPlayType[i] = ((SingleK3) mBetView.mBetList.get(i)).getPlayTypeID();
                    break;
                default:
                    ticket.mPlayType[i] = BetManager.getInstance().getPlayType();
                    break;
            }
            ticket.mMultiTimes[i] = BetManager.getInstance().getTimes();
            ticket.gameBetDataString[i] = betData[i];
        }
        //取第一个投注号码放到 mGameBetData[0][0] 里,用于计算验票码
        try {
            String firstBetNum = betData[0].substring(0, betData[0].indexOf("|"));
            int firstNum = Integer.valueOf(firstBetNum);
            ticket.mGameBetData[0][0] = firstNum;
        } catch (Exception exception) {
            LogTool.logE("ticket.mGameBetData set failed, " + exception.getMessage());
        }
        return ticket;
    }

    private GameTicket getTrainModeTicket(String money) {
        int gameId = BetManager.getInstance().getGameId();
        GameTicket ticket = new GameTicket();
        ticket.mGameID = gameId;
        ticket.mGameIssue = TrainMode.getIssue();
        ticket.mTicketSN = TrainMode.getSN();
        ticket.mBettingMoney = Double.parseDouble(money);
        ticket.mFeatureKey = GameUtil.randomN(0, 254);
        ticket.mTerminalID = SystemNI.getTerminalID();
        //mFeatureCode由mGameID mGameIssue mTicketSN mTerminalID mFeatureKey计算生成
        ticket.mFeatureCode = SystemNI.featureCode(ticket);
        ticket.mMultiIssue = BetManager.getInstance().getIssues();
        ticket.mMemberID = "0";
        ticket.mBettingTime = System.currentTimeMillis() / 1000;
        ticket.mWelfareFundTipsString = "感谢您为公益事业贡献2元";
        String[] betData = mBetView.getBetData();
        LogTool.logD(Arrays.toString(betData));
        ticket.mBets = betData.length;
        for (int i = 0; i < betData.length; i++) {
            //手持终端投注暂时定位1
            ticket.mBettingMode[i] = 1;
            switch (BetManager.getInstance().getPlayType()) {
                case PlayTypeID.D3_ZUXUAN:
                    ticket.mPlayType[i] = ((ZuXuan) mBetView.mBetList.get(i)).getPlayTypeID(0);
                    break;
                case PlayTypeID.D3_PACK:
                    ticket.mPlayType[i] = ((ZuXuan) mBetView.mBetList.get(i)).getPlayTypeID(1);
                    break;
                case PlayTypeID.SSQ_BASE:
                case PlayTypeID.SSQ_BASE_MULTI:
                    ticket.mPlayType[i] = ((BaseSSQ) mBetView.mBetList.get(0)).getPlayTypeID();
                    break;
                case PlayTypeID.K3_SINGLE:
                    ticket.mPlayType[i] = ((SingleK3) mBetView.mBetList.get(i)).getPlayTypeID();
                    break;
                default:
                    ticket.mPlayType[i] = BetManager.getInstance().getPlayType();
                    break;
            }
            ticket.mMultiTimes[i] = BetManager.getInstance().getTimes();
            ticket.gameBetDataString[i] = betData[i];
        }
        //取第一个投注号码放到 mGameBetData[0][0] 里,用于计算验票码
        try {
            String firstBetNum = betData[0].substring(0, betData[0].indexOf("|"));
            int firstNum = Integer.valueOf(firstBetNum);
            ticket.mGameBetData[0][0] = firstNum;
        } catch (Exception exception) {
            LogTool.logE("ticket.mGameBetData set failed, " + exception.getMessage());
        }
        return ticket;
    }

    public void showSingleRandomDialog() {
        CommonDialog.newInstance().setLayoutId(R.layout.dialog_random_single)
                .setConvertListener((ViewConvertListener) (holder, dialog) -> {
                    KeyboardEditText etBets = holder.getView(R.id.et_bets);
                    holder.setOnClickListener(R.id.bt_cancel, v -> dialog.dismiss());
                    holder.setOnClickListener(R.id.bt_confirm, v -> {
                        String bets = etBets.getText().toString().trim();
                        if (TextUtils.isEmpty(bets)) {
                            etBets.setError("注数不能为空");
                            return;
                        }
                        mRandomNum = Integer.parseInt(bets);
                        mOutNum = 0;
                        mLeftNum = mRandomNum;
                        randomNum(mRandomNum);
                        isRandom = true;
                        if (mRandomNum > 5) {
                            isSingleOver5 = true;
                            showRandomMessage();
                        }
                        dialog.dismiss();
                    });
                })
                .setSize(ScreenUtils.getScreenWidth(), ScreenUtils.getScreenHeight())
                .setOutCancel(false)
                .show(activity.getSupportFragmentManager());
    }

    public void showRandomMessage() {
        showTips("已经选择" + mRandomNum + "注,已经出票" + mOutNum + "注,剩余" + mLeftNum + "注");
    }

    @OnClick(R.id.bt_random5)
    public void randomFiveBet() {
        randomNum(5);
    }

    @Override
    public void showTips(String message) {
        activity.runOnUiThread(() -> ((GameActivity) activity).showTips(message));
    }

    @Override
    public void onBetSuccess(double money, int bets) {
        BetManager.getInstance().mTotalSum += money;
        activity.runOnUiThread(() -> {
            if (isSingleOver5) {
                mOutNum += bets;
                mLeftNum = mRandomNum - mOutNum;
                if (mLeftNum > 0) {
                    randomNum(mLeftNum);
                    showRandomMessage();
                } else {
                    clearUI();
                    clearRandom();
                }
            } else {
                clearUI();
            }
        });
    }


    @BindView(R.id.tv_sum)
    public TextView tvSum;
    @BindView(R.id.tv_sum_total)
    public TextView tvSumTotal;
    @BindView(R.id.tv_multi)
    public KeyboardEditText tvMulti;
    @BindView(R.id.bt_random)
    public Button btRandom;
    @BindView(R.id.bt_random5)
    public Button btRandom5;
    @BindView(R.id.bet_frame)
    public FrameLayout frameBet;

}
