package robot.handler;

import com.robot.Util;
import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.plugin.database.DataBase;
import com.taurus.core.util.Logger;
import taurus.client.Message;
import taurus.client.TaurusClient;
import taurus.util.CardUtil;
import taurus.util.ChangShaSuanFaTest;
import taurus.util.ChangshaWinSplitCard;

import java.sql.SQLException;
import java.util.*;

public class HuNanChangShaHandler {

    public static int changShaCard = 0;
    public static boolean isTinChi = false;
    public static boolean isTinPeng = false;

    private static final Logger log = Logger.getLogger(HuNanChangShaHandler.class);


    //湖南长沙麻将手牌
    private final List<Integer> changShaCardInhand = new ArrayList<>();

    private final List<Integer> changShaCardInhandgang = new ArrayList<>();

    //长沙麻将出过的牌
    private final List<Integer> changShachuguopai = new ArrayList<>();

    private final Map<Integer, Integer> chuGuoPainum = new HashMap<>();

    //杠的牌
    private final List<Integer> gangdepai = new ArrayList<>();

    //碰牌
    private final List<Integer> pongGroup = new ArrayList<>();

    //吃牌
    private final List<Integer> chowGroup = new ArrayList<>();

    //玩家座位号
    public static int seat = 0;

    public static int playerId = 0;

    public static int cardToOut1 = 0;

    //会话标识
    public static String session = "";
    //访问令牌
    public static String token = "";

    private static final ChangShaSuanFaTest changShaSuanFaTest = new ChangShaSuanFaTest();


    //公共的getter和setter方法
    public List<Integer> getChangShaCardInhand() {
        return changShaCardInhand;
    }

    public List<Integer> getGangdepai() {
        return gangdepai;
    }

    public List<Integer> getChangShaCardInhandgang() {
        return changShaCardInhandgang;
    }

    public List<Integer> getPongGroup() {
        return pongGroup;
    }

    public List<Integer> getChowGroup() {
        return chowGroup;
    }

    public List<Integer> getChuGuoCardInhand() {
        return changShachuguopai;
    }

    public Map<Integer, Integer> getChuGuoPainum() {
        return chuGuoPainum;
    }
    
    /**
     * 设置会话和令牌
     */
    public void setSessionAndToken(String session, String token) {
        HuNanChangShaHandler.session = session;
        HuNanChangShaHandler.token = token;
    }

    /**
     * 出牌广播协议 812
     *
     * @param command 协议号
     * @param message 消息对象
     */
    public static void drawCard(String command, Message message) {
        if (command.equalsIgnoreCase("812")) {
            ITObject param = message.param;
            if (param == null) {
                return;
            }
            changShaCard = param.getInt("card");

        }
    }

    /**
     * 摸牌协议 819
     *
     * @param command 协议号
     * @param message 消息对象
     */
    public void getCard(String command, Message message) {
        if (command.equalsIgnoreCase("819")) {
            ITObject param = message.param;
            if (param == null) {
                return;
            }

            if (param.getInt("player") != null) {
                int drawnCard = param.getInt("card");
                changShaSuanFaTest.drawnCards = drawnCard;
                changShaCardInhand.add(drawnCard);
                changShaSuanFaTest.analyzeHand(changShaCardInhand);
            }
        }
    }

    /**
     * 初始化手牌协议 811
     *
     * @param command 协议号
     * @param message 消息对象
     */
    public void cardInHead(String command, Message message, TaurusClient client) {
        if (command.equalsIgnoreCase("811")) {
            ITObject param = message.param;
            if (param == null) {
                return;
            }

            ITArray cardList = param.getTArray("card_list");
            changShaCardInhand.clear();
            for (int i = 0; i < cardList.size(); i++) {
                changShaCardInhand.add(cardList.getInt(i));
            }
        }
    }

    /**
     * 处理 吃，碰，杠，补，胡
     */
    public void actionCard(ITObject param, TaurusClient client) {
        ITArray tipList = param.getTArray("tip_list");
        log.info("tipList" +tipList);
        ITObject params = TObject.newInstance();
        int card = 0;

        //循环
        List<Integer> yupanhandcard = new ArrayList<>(changShaCardInhand);
        //进行操作之前能否下听
        List<Integer> shifoutingpai = ChangShaSuanFaTest.handscardshifoutingpai(changShaCardInhand,chowGroup,pongGroup,gangdepai);
        //记录操作之前的下听状态
        boolean beforelisten = false;
        if (!shifoutingpai.isEmpty()) {
            beforelisten = true;
        }

        //如果杠了之后还能继续听牌则杠
        //如果下听了，可以杠
        for (int i = 0; i < tipList.size(); i++) {
            TObject firstTip = (TObject) tipList.get(i).getObject();
            int type = firstTip.getInt("type");
            int id = firstTip.getInt("id");
            int weight = firstTip.getInt("weight");
            card = firstTip.getInt("card");


            if (type == 6){
                params.putString("session", session + "," + token);
                params.putInt("qi", 0);
                params.putInt("id", id);
                client.send("612", params, response -> {
                });
                return;
            }

            if ((type == 5 || type == 3 || type==4)&&weight==4) {
                //判断开杠后是否能下听
                List<Integer> gangusecars = new ArrayList<>(changShaCardInhand);

                if (type == 3) {
                    Util.removeCard(gangusecars,card,3);
                    List<Integer> shifoutingpai3 = ChangShaSuanFaTest.handscardshifoutingpai(gangusecars,chowGroup,pongGroup,gangdepai);
                    log.info(shifoutingpai3);

                    if (!shifoutingpai3.isEmpty()) {
                        //开杠
                        //判断是否杠了之后没有牌可以听
                        List<Integer> allList = new ArrayList<>();
                        allList.addAll(changShaCardInhand);
                        allList.addAll(changShachuguopai);
                        int jutingnum =  ChangShaSuanFaTest.getTingPainum(shifoutingpai3,allList);
                        if (jutingnum==0){
                            params.putString("session", session + "," + token);
                            params.putInt("qi", 0);
                            params.putInt("id", 0);
                            client.send("612", params, response -> {
                            });
                            return;
                        }

                        Util.removeCard(changShaCardInhand,card,3);
                        params.putString("session", session + "," + token);
                        params.putInt("qi", 0);
                        params.putInt("id", id);
                        client.send("612", params, response -> {
                        });
                        return;
                    }else{
                        params.putString("session", session + "," + token);
                        params.putInt("qi", 0);
                        params.putInt("id", 0);
                        client.send("612", params, response -> {
                        });
                        return;
                    }
                }
                if (type == 4) {
                    Util.removeCard(gangusecars,card,4);
                    List<Integer> shifoutingpai4 = ChangShaSuanFaTest.handscardshifoutingpai(gangusecars,chowGroup,pongGroup,gangdepai);
                    if (!shifoutingpai4.isEmpty()) {
                        //开杠
                        //判断是否杠了之后没有牌可以听
                        List<Integer> allList = new ArrayList<>();
                        allList.addAll(changShaCardInhand);
                        allList.addAll(changShachuguopai);
                        int jutingnum =  ChangShaSuanFaTest.getTingPainum(shifoutingpai4,allList);
                        if (jutingnum==0){
                            params.putString("session", session + "," + token);
                            params.putInt("qi", 0);
                            params.putInt("id", 0);
                            client.send("612", params, response -> {
                            });
                            return;
                        }

                        Util.removeCard(changShaCardInhand,card,4);
                        params.putString("session", session + "," + token);
                        params.putInt("qi", 0);
                        params.putInt("id", id);
                        client.send("612", params, response -> {
                        });
                        return;
                    }else{
                        params.putString("session", session + "," + token);
                        params.putInt("qi", 0);
                        params.putInt("id", 0);
                        client.send("612", params, response -> {
                        });
                        return;
                    }
                }
                if (type == 5) {

                    Util.removeCard(gangusecars,card,1);
                    List<Integer> shifoutingpai5 = ChangShaSuanFaTest.handscardshifoutingpai(gangusecars,chowGroup,pongGroup,gangdepai);
                    if (!shifoutingpai5.isEmpty()) {
                        //开杠
                        //判断是否杠了之后没有牌可以听
                        List<Integer> allList = new ArrayList<>();
                        allList.addAll(changShaCardInhand);
                        allList.addAll(changShachuguopai);
                        int jutingnum =  ChangShaSuanFaTest.getTingPainum(shifoutingpai5,allList);
                        if (jutingnum==0){
                            params.putString("session", session + "," + token);
                            params.putInt("qi", 0);
                            params.putInt("id", 0);
                            client.send("612", params, response -> {
                            });
                            return;
                        }

                        Util.removeCard(changShaCardInhand,card,1);
                        params.putString("session", session + "," + token);
                        params.putInt("qi", 0);
                        params.putInt("id", id);
                        client.send("612", params, response -> {
                        });
                        return;
                    }else{
                        params.putString("session", session + "," + token);
                        params.putInt("qi", 0);
                        params.putInt("id", 0);
                        client.send("612", params, response -> {
                        });
                        return;
                    }
                }


            }
        }

        //判断是否是大胡
        int beforeIsDahu = 0;
        beforeIsDahu = ChangShaSuanFaTest.checkDahu(yupanhandcard,chowGroup,pongGroup,gangdepai);
        //5、门清
        if (yupanhandcard.size()==13&&beforelisten){
            beforeIsDahu = 5;//门清
        }

        //操作之前出现的牌
        List<Integer> allSeeCard = new ArrayList<>();

        Map<Integer,ITObject> pingfenResult = new HashMap<>();
        Map<Integer,ITObject> idObject = new HashMap<>();
        for (int i = 0; i < tipList.size(); i++) {
            TObject firstTip = (TObject) tipList.get(i).getObject();
            int type = firstTip.getInt("type");
            int id = firstTip.getInt("id");
            int weight = firstTip.getInt("weight");
            card = firstTip.getInt("card");
            ITArray opcard =  firstTip.getTArray("opcard");
            if (type == 6){
                params.putString("session", session + "," + token);
                params.putInt("qi", 0);
                params.putInt("id", id);
                client.send("612", params, response -> {
                });
                return;
            }
            //对应的数据
            ITObject tmp = new TObject();
            //处理听的结果
            switch (type) {
                case 1:
                    //吃
                    tmp = ChangShaSuanFaTest.pingguChi( beforelisten,card,opcard,yupanhandcard,beforeIsDahu,allSeeCard,chowGroup,pongGroup,gangdepai,changShachuguopai);
                    break;
                case 2:
                    //碰
                    tmp = ChangShaSuanFaTest.pingguPeng(beforelisten,card,opcard,yupanhandcard,beforeIsDahu,allSeeCard,chowGroup,pongGroup,gangdepai,changShachuguopai);
                    break;
                default:
                    break;
            }
            //记录下来事件
            if(tmp.size()>0){
                pingfenResult.put(id,tmp);
            }
            ITObject sj = new TObject();
            sj.putInt("weight", weight);
            sj.putTArray("opcard", opcard);
            idObject.put(id,sj);
        }
        //计算分数
        log.info(pingfenResult);
        if(!pingfenResult.isEmpty()){
            int changeid= ChangShaSuanFaTest.suanfen(pingfenResult);
            log.info("changeid:"+changeid);
            //选择最优的分数
            if (changeid==0){
                params.putString("session", session + "," + token);
                params.putInt("qi", 0);
                params.putInt("id", 0);
                client.send("612", params, response -> {
                });
                return;
            }else {
                //获取
                for(Map.Entry<Integer,ITObject> entry : idObject.entrySet()){
                    if(entry.getKey()==changeid){
                        ITObject tmp = entry.getValue();
                        if (tmp.getInt("weight")==2){
                            //碰
                            ITArray outcards = tmp.getTArray("opcard");
                            for (int i = 0; i < outcards.size(); i++) {
                                Util.removeCard(changShaCardInhand,outcards.getInt(0),2);
                            }
                        }else if (tmp.getInt("weight")==1){
                            //吃
                            ITArray outcards = tmp.getTArray("opcard");
                            for (int i = 0; i < outcards.size(); i++) {
                                Util.removeCard(changShaCardInhand,outcards.getInt(i),1);
                            }
                        }
                    }
                }
                params.putString("session", session + "," + token);
                params.putInt("qi", 0);
                params.putInt("id", changeid);
                client.send("612", params, response -> {
                });
                return;
            }
        }

        //计算牌数

        //如果 不吃，不碰，而且差三手牌情况，则补
        for (int i = 0; i < tipList.size(); i++) {
            TObject firstTip = (TObject) tipList.get(i).getObject();
            int type = firstTip.getInt("type");
            int id = firstTip.getInt("id");
            int weight = firstTip.getInt("weight");
            card = firstTip.getInt("card");

            Map<String, Object> map = new HashMap<>();
            List<Integer> tmpChangSch = new ArrayList<>(yupanhandcard);
            ChangshaWinSplitCard.checkNormalHu(tmpChangSch, map);
            System.out.println("map:" + map);

            if (!map.isEmpty() && weight==3) {

                if (Integer.parseInt(map.get("remainingMelds").toString()) > 2) {
                    params.putString("session", session + "," + token);
                    params.putInt("qi", 0);
                    params.putInt("id", id);

                    if (type == 3) {
                        Util.removeCard(changShaCardInhand,card,3);
                    }
                    if (type == 4) {
                        Util.removeCard(changShaCardInhand,card,4);
                    }
                    if (type == 5) {
                        Util.removeCard(changShaCardInhand,card,1);
                    }
                    client.send("612", params, response -> {
                    });
                    return;
                } else {
                    params.putString("session", session + "," + token);
                    params.putInt("qi", 0);
                    params.putInt("id", 0);
                    client.send("612", params, response -> {
                    });
                    return;
                }
            }
        }
        params.putString("session", session + "," + token);
        params.putInt("qi", 0);
        params.putInt("id", 0);
        client.send("612", params, response -> {
        });
    }


    /**
     * 出牌方法
     */
    public void outCard(TaurusClient client, Map<Integer, List<Integer>> playerOutcardsMap,
                        Map<Integer, List<Integer>> playerchisMap, Map<Integer, List<Integer>> playerpengsMap,
                        Map<Integer, List<Integer>> playermingsMap, Map<Integer, List<Integer>> playerzisMap) {
        //整合所有其他玩家的出牌信息
        List<Integer> resultList = new ArrayList<>();
        for (List<Integer> cards : playerOutcardsMap.values()) {
            resultList.addAll(cards);
        }

        for (List<Integer> chis : playerchisMap.values()) {
            resultList.addAll(chis);
        }

        for (List<Integer> pengs : playerpengsMap.values()) {
            resultList.addAll(pengs);
        }

        for (List<Integer> minggangs : playermingsMap.values()) {
            resultList.addAll(minggangs);
        }

        for (List<Integer> zigang : playerzisMap.values()) {
            resultList.addAll(zigang);
        }

        ITObject params = TObject.newInstance();
        int cardToOut;

        if (!changShaCardInhand.isEmpty()) {
            //使用长沙麻将算法计算最优出牌
            ChangShaSuanFaTest changShaSuanFaTest = new ChangShaSuanFaTest();
            String cardStr = changShaSuanFaTest.outCardSuanFa(changShaCardInhand, pongGroup, chowGroup, gangdepai, resultList);
            try {
                cardToOut = Integer.parseInt(cardStr);
            } catch (NumberFormatException e) {
                //如果算法出错，使用第一张牌
                cardToOut = changShaCardInhand.get(0);
            }
        } else {
            return; //没有牌可出
        }

        params.putInt("card", cardToOut);

        int outCountBefore = changShachuguopai.size(); //当前历史出牌数量

        //第n次出牌时，发送前n-1张出牌
        if (outCountBefore >= 1) {
            //发送前n-1张（所有历史出牌）
            List<Integer> cardsToSend = changShachuguopai.subList(0, outCountBefore);
            params.putTArray("outcard_list", CardUtil.maJiangToTArray(cardsToSend));
        }
        params.putTArray("card_list", CardUtil.maJiangToTArray(changShaCardInhand));


        //将当前出的牌添加到历史出牌列表
        changShachuguopai.add(cardToOut);
        //从手牌中移除
        changShaCardInhand.remove(Integer.valueOf(cardToOut));

        params.putString("session", session + "," + token);
        client.send("611", params, response -> {
        });

    }


    /**
     * 删除出过的牌组
     *
     */
    public void shanchuchuguopai(ITObject param) {
        if (param == null) {
            return;
        }

        Integer card = param.getInt("card"); //操作牌值
        Integer type = param.getInt("type"); //操作类型
        Integer from_seat = param.getInt("from_seat"); //牌来源座位


        Integer playerid = param.getInt("playerid");


        String sql2 = "SELECT id FROM `account` WHERE jiqiren=9998";
        try {
            ITArray robotId2 = DataBase.use().executeQueryByTArray(sql2);
            List<Integer> robotIdsList = new ArrayList<>();

            for (int j = 0; j < robotId2.size(); j++) {
                robotIdsList.add(robotId2.getTObject(j).getInt("id"));
            }

            if (!robotIdsList.contains(playerid)) {
                if (type == 2 || type == 3 || type == 5 || type == 1) { //碰，杠
                    getChuGuoCardInhand().remove(card);
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 位置转换协议 820
     *
     * @param command 协议号
     * @param message 消息对象
     */
    public static void changePlayer(String command, Message message) {
        if (command.equalsIgnoreCase("820")) {
            ITObject param = message.param;
            if (param == null) {
                return;
            }

            seat = param.getInt("seat");
        }
    }
}