package com.genlot.ninglottery.toolkit;

import com.genlot.nativesdk.model.GameTicket;
import com.genlot.ninglottery.game.bet.BetManager;
import com.genlot.ninglottery.model.GameIDSet;
import com.genlot.ninglottery.model.PlayTypeID;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

/**
 * @author ZhuYongKang
 * @description 游戏相关公共方法
 * @date 2019 /7/25
 */
public class GameUtil {

    /**
     * 获取随机数组
     *
     * @param min 最小值
     * @param max 最大值
     * @param n   数量
     * @return the int [ ]
     */
    public static int[] randomCommon(int min, int max, int n) {
        int[] result = new int[n];
        if (n > (max - min + 1) || max < min) {
            return result;
        }
        int count = 0;
        Random rand = new Random();
        while (count < n) {
            int num = rand.nextInt(max - min + 1) + min;
            boolean flag = true;
            for (int j = 0; j < n; j++) {
                if (num == result[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                result[count] = num;
                count++;
            }
        }
        //排序，从小到大
        Arrays.sort(result);
        return result;
    }

    /**
     * 获取随机有序列表
     *
     * @param min 最小值
     * @param max 最大值
     * @param n   数量
     * @return 随机有序列表 list
     */
    public static Set<Integer> randomList(int min, int max, int n) {
        Set<Integer> set = new TreeSet<>();
        if (n > (max - min + 1) || max < min) {
            return set;
        }
        Random rand = new Random();
        while (set.size() < n) {
            int num = rand.nextInt(max - min + 1) + min;
            set.add(num);
        }
        return set;
    }

    /**
     * 从列表中随机截取n
     *
     * @param list 要截取列表
     * @param n    截取数
     * @return 截取后列表
     */
    public static Set<Integer> randomSplitList(List<Integer> list, int n) {
        Set<Integer> set = new TreeSet<>();
        Random rand = new Random();
        for (int i = 0; i < n; i++) {
            int index = rand.nextInt(list.size());
            set.add(list.get(index));
            list.remove(index);
        }

        return set;
    }

    /**
     * 计算C(n,m)
     *
     * @param N 总数
     * @param M 取m个数字
     * @return the long
     */
    public static long C(int N, int M) {
        if (N <= 0 || N < M) {
            return 0;
        }
        if (M > (int)Math.ceil(N / 2.0)) {
            return C(N, N - M);
        }
        long sum = 1;
        for (int i = 1; i <= M; i++) {
            sum = sum * (N - M + i) / i;
        }
        return sum;
    }


    /**
     * Parse status string.
     *
     * @param status 状态码
     * @return the string
     */
    public static String parseStatus(int status) {
        switch (status) {
            case 0:
            case 2:
                return "已注销";
            case 1:
                return "已冲正";
            case 3:
                return "有效";
            case 4:
            case 5:
                return "已兑奖";
            case 6:
                return "弃奖";
            default:
                return "有效";
        }
    }


    private static String[] betSerials = {"①", "②", "③", "④", "⑤"};

    private static String parseSSQTicket(GameTicket ticket) {
        String[] betData = ticket.gameBetDataString;
        StringBuilder sb = new StringBuilder();
        switch (ticket.mPlayType[0]) {
            case PlayTypeID.SSQ_SINGLE:
                for (int i = 0; i < ticket.mBets; i++) {
                    sb.append(betSerials[i]).append(" ");
                    String[] singleNums = betData[i].split("-");
                    String[] numRed = singleNums[0].split("\\|");
                    String[] numBlue = singleNums[1].split("\\|");
                    for (String red : numRed) {
                        sb.append(StringTool.format2(Integer.parseInt(red))).append(" ");
                    }
                    sb.append("-");
                    for (String blue : numBlue) {
                        sb.append(StringTool.format2(Integer.parseInt(blue))).append(" ");
                    }
                    if (i == 0) {
                        sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[i]));
                    }
                    if (i != ticket.mBets - 1) {
                        sb.append("<br/>");
                    }
                }
                break;
            case PlayTypeID.SSQ_MULTI:
                String[] multiNums = betData[0].split("-");
                String[] numRed = multiNums[0].split("\\|");
                String[] numBlue = multiNums[1].split("\\|");
                for (String red : numRed) {
                    sb.append(StringTool.format2(Integer.parseInt(red))).append("+");
                }
                sb.setCharAt(sb.length()-1,'-');
                for (String blue : numBlue) {
                    sb.append(StringTool.format2(Integer.parseInt(blue))).append("+");
                }
                sb.setCharAt(sb.length()-1,' ');
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
                break;
            case PlayTypeID.SSQ_BASE:
            case PlayTypeID.SSQ_BASE_MULTI:
                String[] baseNums = betData[0].split("-");
                String[] numDan = baseNums[0].split("\\|");
                String[] numTuo = baseNums[1].split("\\|");
                String[] numsBlue = baseNums[2].split("\\|");
                for (String dan : numDan) {
                    sb.append(StringTool.format2(Integer.parseInt(dan))).append("+");
                }
                sb.setCharAt(sb.length()-1,'^');
                for (String tuo : numTuo) {
                    sb.append(StringTool.format2(Integer.parseInt(tuo))).append("+");
                }
                sb.setCharAt(sb.length()-1,'-');
                for (String blue : numsBlue) {
                    sb.append(StringTool.format2(Integer.parseInt(blue))).append("+");
                }
                sb.setCharAt(sb.length()-1,' ');
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
                break;
        }
        return sb.toString();
    }

    private static String parse3DTicket(GameTicket ticket) {
        String[] betData = ticket.gameBetDataString;
        StringBuilder sb = new StringBuilder();
        if (ticket.mPlayType[0] == PlayTypeID.D3_MULTI) {
            String[] nums = betData[0].split("-");
            String[] numsBai = nums[0].split("\\|");
            String[] numsShi = nums[1].split("\\|");
            String[] numsGe = nums[2].split("\\|");
            sb.append("[百]").append(" ");
            for (String num : numsBai) {
                sb.append(num).append(" ");
            }
            sb.append("<br/>");
            sb.append("[十]").append(" ");
            for (String num : numsShi) {
                sb.append(num).append(" ");
            }
            sb.append("<br/>");
            sb.append("[个]").append(" ");
            for (String num : numsGe) {
                sb.append(num).append(" ");
            }
            sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
            return sb.toString();
        }
        if (ticket.mPlayType[0] == PlayTypeID.D3_BASE || ticket.mPlayType[0] == PlayTypeID.D3_BASE_BOX
                || ticket.mPlayType[0] == PlayTypeID.D3_BASE_BOX3 || ticket.mPlayType[0] == PlayTypeID.D3_BASE_BOX6) {
            String[] nums = betData[0].split("-");
            String[] numDan = nums[0].split("\\|");
            String[] numTuo = nums[1].split("\\|");
            for (String dan : numDan) {
                sb.append(dan).append("+");
            }
            sb.setCharAt(sb.length() - 1, '^');
            for (String tuo : numTuo) {
                sb.append(tuo).append("+");
            }
            sb.setCharAt(sb.length() - 1, ' ');
            sb.append("[").append(BetManager.getInstance().getTimes()).append("倍]");
            return sb.toString();
        }
        for (int i = 0; i < ticket.mBets; i++) {
            String[] nums = betData[i].split("\\|");
            if (ticket.mBets > 1) {
                sb.append(betSerials[i]).append(" ");
            }
            switch (ticket.mPlayType[0]) {
                case PlayTypeID.D3_STRAIGHT_BASE:
                    for (int j = 0; j < nums.length; j++) {
                        if (j == nums.length - 1) {
                            sb.append(nums[j]).append(" ");
                        } else {
                            sb.append(nums[j]).append("+");
                        }
                    }
                    break;
                case PlayTypeID.D3_GUESS_BS:
                case PlayTypeID.D3_GUESS_OE:
                    for (String num : nums) {
                        if (num.equals("1")) {
                            sb.append("小").append(" ");
                        } else if(num.equals("2")){
                            sb.append("大").append(" ");
                        } else if (num.equals("4")) {
                            sb.append("偶").append(" ");
                        } else if (num.equals("5")) {
                            sb.append("奇").append(" ");
                        }
                    }
                    break;
                case PlayTypeID.D3_1D:
                case PlayTypeID.D3_2D:
                    for (String num : nums) {
                        if (num.equals("255")) {
                            sb.append("-").append(" ");
                        } else {
                            sb.append(num).append(" ");
                        }
                    }
                    break;
                case PlayTypeID.D3_GUESS_3SAME:
                    sb.append("三同号").append(" ");
                    break;
                case PlayTypeID.D3_TRACTOR:
                    sb.append("拖拉机").append(" ");
                    break;
                case PlayTypeID.D3_STRAIGHT_ALL_BOX3:
                    sb.append("- - - ");
                    break;
                case PlayTypeID.D3_DIFFERENCE:
                    sb.append("DX-KD:").append("[").append(nums[0]).append("]").append(" ");
                    break;
                case PlayTypeID.D3_DIFFERENCE_BOX3:
                    sb.append("ZUX3-KD:").append("[").append(nums[0]).append("]").append(" ");
                    break;
                case PlayTypeID.D3_DIFFERENCE_BOX6:
                    sb.append("ZUX6-KD:").append("[").append(nums[0]).append("]").append(" ");
                    break;
                case PlayTypeID.D3_ZHIXUAN_BIT_MULTI:
                    for (String num : nums) {
                        if (num.equals("255")) {
                            sb.append("*").append(" ");
                        } else {
                            sb.append(num).append(" ");
                        }
                    }
                    break;
                case PlayTypeID.D3_SUM:
                    for (String num : nums) {
                        sb.append(StringTool.format2(Integer.parseInt(num))).append(" ");
                    }
                    break;
                case PlayTypeID.D3_MULTI_BOX3:
                case PlayTypeID.D3_MULTI_BOX6:
                case PlayTypeID.D3_MULTI_STRAIGHT_BOX3:
                case PlayTypeID.D3_MULTI_STRAIGHT_BOX6:
                case PlayTypeID.D3_STRING:
                    for (String num : nums) {
                        sb.append(num).append("+");
                    }
                    sb.setCharAt(sb.length() - 1,' ');
                    break;
                default:
                    for (String num : nums) {
                        try {
                            int anInt = Integer.parseInt(num);
                            sb.append(num).append(" ");
                        } catch (Exception e) {
                            LogTool.logW(num + "is not number");
                        }
                    }
                    break;
            }
            if (i == 0) {
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[i]));
            }
            if (i != ticket.mBets - 1) {
                sb.append("<br/>");
            }
        }
        return sb.toString();
    }

    private static String parseSLCTicket(GameTicket ticket) {
        String[] betData = ticket.gameBetDataString;
        StringBuilder sb = new StringBuilder();
        switch (ticket.mPlayType[0]) {
            case PlayTypeID.STAR_7_SINGLE:
                for (int i = 0; i < ticket.mBets; i++) {
                    sb.append(betSerials[i]).append(" ");
                    String[] nums = betData[i].split("\\|");
                    for (String num : nums) {
                        sb.append(StringTool.format2(Integer.parseInt(num))).append(" ");
                    }
                    if (i == 0) {
                        sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[i]));
                    }
                    if (i != ticket.mBets - 1) {
                        sb.append("<br/>");
                    }
                }
                break;
            case PlayTypeID.STAR_7_MULTI:
                String[] multiNums = betData[0].split("\\|");
                for (String num : multiNums) {
                    sb.append(StringTool.format2(Integer.parseInt(num))).append("+");
                }
                sb.setCharAt(sb.length() - 1,' ');
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
                break;
            case PlayTypeID.STAR_7_BASE_ROUND:
                String[] baseNums = betData[0].split("-");
                String[] numDan = baseNums[0].split("\\|");
                String[] numTuo = baseNums[1].split("\\|");
                for (String dan : numDan) {
                    sb.append(StringTool.format2(Integer.parseInt(dan))).append("+");
                }
                sb.setCharAt(sb.length() - 1, '^');
                for (String tuo : numTuo) {
                    sb.append(StringTool.format2(Integer.parseInt(tuo))).append("+");
                }
                sb.setCharAt(sb.length() - 1, ' ');
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
                break;
        }
        return sb.toString();
    }

    private static String parseK3Ticket(GameTicket ticket) {
        String[] betData = ticket.gameBetDataString;
        StringBuilder sb = new StringBuilder();
        switch (ticket.mPlayType[0]) {
            case PlayTypeID.K3_3NUMBER_SINGLE:
            case PlayTypeID.K3_2NUMBER_MULTI:
            case PlayTypeID.K3_2NUMBER_SINGLE:
            case PlayTypeID.K3_3NUMBER_DIFF:
            case PlayTypeID.K3_2NUMBER_DIFF:
                for (int i = 0; i < ticket.mBets; i++) {
                    sb.append(betSerials[i]).append(" ");
                    String[] nums = betData[i].split("\\|");
                    for (String num : nums) {
                        sb.append(num.equals("255") ? "*" : num).append(" ");
                    }
                    if (i == 0) {
                        sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[i]));
                    }
                    if (i != ticket.mBets - 1) {
                        sb.append("<br/>");
                    }
                }
                break;
            case PlayTypeID.K3_SUM:
                for (int i = 0; i < ticket.mBets; i++) {
                    sb.append(betSerials[i]).append(" ");
                    String[] nums = betData[i].split("\\|");
                    for (String num : nums) {
                        sb.append(StringTool.format2(Integer.parseInt(num))).append(" ");
                    }
                    if (i == 0) {
                        sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[i]));
                    }
                    if (i != ticket.mBets - 1) {
                        sb.append("<br/>");
                    }
                }
                break;
            case PlayTypeID.K3_3NUMBER_ALL:
                sb.append("三同号通选").append(" ");
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
                break;
            case PlayTypeID.K3_3NUMBER_SERIAL:
                sb.append("三连号通选").append(" ");
                sb.append(String.format(Locale.getDefault(), "[%d倍]", ticket.mMultiTimes[0]));
                break;
        }
        return sb.toString();
    }

    /**
     * 解析游戏号码 注销界面使用
     * @param ticket   GameTicket
     * @return  String
     */
    public static String parseTicketNum(GameTicket ticket) {
        switch (ticket.mGameID) {
            case GameIDSet.GAME_ID_SSQ:
                return parseSSQTicket(ticket);
            case GameIDSet.GAME_ID_3D:
                return parse3DTicket(ticket);
            case GameIDSet.GAME_ID_SLC:
                return parseSLCTicket(ticket);
            case GameIDSet.GAME_ID_K3:
                return parseK3Ticket(ticket);
            default:
                return "";
        }
    }

    /**
     * 判断是否是手机号码
     *
     * @param input 输入字符串
     * @return the boolean
     */
    public static boolean isPhoneNumber(String input) {
        String regex = "(1[0-9][0-9]|15[0-9]|18[0-9])\\d{8}";
        Pattern p = Pattern.compile(regex);
        return p.matcher(input).matches();
    }

    public static int randomN(int min, int max) {
        return (int) (Math.random() * (max - min + 1) + min);
    }

    /**
     * 获得包点有效注数
     * @param sum 和值
     * @return  注数
     */
    public static long getBoxSumBets(int sum) {
        long nums = 0;
        for (int i = 0; i <= 9; i++) {
            for (int j = i; j <= 9; j++) {
                int left = sum - i - j;
                if (left < j) {
                    break;
                }
                if (left > 9) {
                    continue;
                }
                if (i == j && i == left) {
                    nums += 1;
                } else if (i != j && j != left) {
                    nums += 6;
                } else {
                    nums += 3;
                }
            }
        }
        return nums;
    }

    /**
     * 获得组三包点有效注数
     * @param sum 和值
     * @return  注数
     */
    public static long getBox3SumBets(int sum) {
        long nums = 0;
        for (int i = 0; i <= 9; i++) {
            int left = sum - i - i;
            if (left >= 0 && left <= 9 && left != i) {
                nums += 1;
            }
        }
        return nums;
    }

    /**
     * 获得组六包点有效注数
     * @param sum 和值
     * @return  注数
     */
    public static long getBox6SumBets(int sum) {
        long nums = 0;
        for (int i = 0; i <= 9; i++) {
            for (int j = i + 1; j <= 9; j++) {
                int left = sum - i - j;
                if (left < j) {
                    break;
                }
                if (left > 9) {
                    continue;
                }
                if (j != left) {
                    nums += 1;
                }
            }
        }
        return nums;
    }

    /**
     * 获得游戏的玩法
     * @param playTypes 玩法ID数组
     * @param n 投注注数
     * @return 玩法ID
     */
    public static int getPlayType(int[] playTypes, int n) {
        int type = playTypes[0];
        switch (type) {
            case PlayTypeID.D3_ZUSAN:
            case PlayTypeID.D3_ZULIU:
                for (int i = 0; i < n; i++) {
                    if (playTypes[i] != type) {
                        return PlayTypeID.D3_ZUXUAN;
                    }
                }
                break;
            case PlayTypeID.D3_PACK3:
            case PlayTypeID.D3_PACK6:
                for (int i = 0; i < n; i++) {
                    if (playTypes[i] != type) {
                        return PlayTypeID.D3_PACK;
                    }
                }
                break;
            case PlayTypeID.K3_3NUMBER_SINGLE:
            case PlayTypeID.K3_2NUMBER_MULTI:
            case PlayTypeID.K3_2NUMBER_SINGLE:
            case PlayTypeID.K3_3NUMBER_DIFF:
            case PlayTypeID.K3_2NUMBER_DIFF:
                for (int i = 0; i < n; i++) {
                    if (playTypes[i] != type) {
                        return PlayTypeID.K3_SINGLE;
                    }
                }
                break;
            default:
                return type;
        }
        return type;
    }

}
