# -*- coding: utf-8 -*-
# @Time       : 2020/10/1 21:32
# @Author     : Duofeng Wu
# @File       : action.py
# @Description: 动作类
import copy
import json
from state import State
from random import randint
import numpy as np
from ws4py.client.threadedclient import WebSocketClient

import my_utils

trans = {'A': 14, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12,
                 'K': 13, 'B':16,'R':17, 'JOKER': 16,'PASS': 10000000000000, 'Straight': 6, 'TripsPair': 1, 'ThreeWithTwo': 6,
                 'ThreePair': 1, 'Trips': 36, 'Pair': 1296, 'Single': 7776, 'Bomb': 279936, 'StraightFlush': 279936,
                 'back': 1, 'tribute': 1}

tran_score = {"Single": 10,
              "Pair": 5,
              "Trips": 0,
              "ThreePair": -5,
              "ThreeWithTwo": -5,
              "TwoTrips": -5,
              "Straight": 5,
              "StraightFlush": 50,
              "Bomb": 30,
              "PASS": 0,
              'tribute': 0,
              'back': 0
              }
# 中英文对照表
ENG2CH = {
    "Single": "单张",
    "Pair": "对子",
    "Trips": "三张",
    "ThreePair": "三连对",
    "ThreeWithTwo": "三带二",
    "TwoTrips": "钢板",
    "Straight": "顺子",
    "StraightFlush": "同花顺",
    "Bomb": "炸弹",
    "PASS": "过"
}

class BucketClient(WebSocketClient):
    def __init__(self, url):
        super().__init__(url)
        self.state = State()
        self.action = Action()
        self.position = None

    def opened(self):
        pass

    def closed(self, code, reason=None):
        print("Closed down", code, reason)

    def received_message(self, message):
        message = json.loads(str(message))  # 先序列化收到的消息，转为Python中的字典
        result = self.state.parse(message)  # 调用状态对象来解析状态
        stage = result[0]
        m_type = result[1]
        if m_type == 'notify':
            if stage == 'beginning':
                self.position = result[3]
            if stage == 'episodeOver':
                pass
                # print('my pos',self.position,' order',result[2])
        if "actionList" in message:  # 需要做出动作选择时调用动作对象进行解析
            '''if stage == 'play':
                greater_pos = result[7]
                greater_action = result[8]
                if greater_pos == -1:
                    greater_pos = self.position
                if (greater_pos - self.position + 4) %4 == 2:
                    teammate=True
                    team_action = greater_action
                else:
                    teammate=False
                    team_action = None
                act_index = self.action.parse(message,teammate=teammate,teammate_cards=team_action)
            else:'''
            act_index = self.action.parse(message)
            self.send(json.dumps({"actIndex": act_index}))


class Action(object):

    def __init__(self):
        self.action = []
        self.act_range = -1
        self.tran = trans.copy()
        self.rough=[0 for i in range(18)]
        self.curRank = ''
        self.all_match = 0

    def parse(self, msg, bucket_id=-1, teammate=False, teammate_cards=None):
        convert2str = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K']

        self.action = msg["actionList"]
        self.act_range = msg["indexRange"]
        self.curRank = msg['curRank']
        self.tran = trans.copy()
        self.tran[msg['curRank']] = 15
        # print(self.action)
        # print("可选动作范围为：0至{}".format(self.act_range))
        l=len(msg['handCards'])
        self.rough = [0 for i in range(18)]
        self.read(msg['handCards'])

        public = msg['publicInfo']
        current_rank = my_utils.rank2int(self.curRank)

        if bucket_id != -1:
            legal_actions = self.action
            action_bucket = my_utils.decode_action(bucket_id)
            action_rank = action_bucket[1]
            action_type = action_bucket[0]
            if action_rank == 'Red Heart':
                assert action_type == 'Single' or action_type == 'Pair'
                for index in range(len(legal_actions)):
                    action = legal_actions[index]
                    card_str = 'H' + convert2str[current_rank - 1]
                    if action[0] == action_bucket[0] and action[1] == convert2str[current_rank - 1]:
                        if action_type == 'Single':
                            if action[2][0] == card_str:
                                return index
                        if action_type == 'Pair':
                            if action[2][0] == card_str and action[2][1] == card_str:
                                return index
                return None
            elif action_rank == 'Black Joker':
                assert action_type == 'Single' or action_type == 'Pair'
                for index in range(len(legal_actions)):
                    action = legal_actions[index]
                    card_str = 'SB'
                    if action[0] == action_bucket[0] and action[1] == 'B':
                        if action_type == 'Single':
                            if action[2][0] == card_str:
                                return index
                        if action_type == 'Pair':
                            if action[2][0] == card_str and action[2][1] == card_str:
                                return index
                return None
            elif action_rank == 'Red Joker':
                assert action_type == 'Single' or action_type == 'Pair'
                for index in range(len(legal_actions)):
                    action = legal_actions[index]
                    card_str = 'HR'
                    if action[0] == action_bucket[0] and action[1] == 'R':
                        if action_type == 'Single':
                            if action[2][0] == card_str:
                                return index
                        if action_type == 'Pair':
                            if action[2][0] == card_str and action[2][1] == card_str:
                                return index
                return None
            elif action_rank == 'JOKER':
                assert action_type == 'Bomb'
                for index in range(len(legal_actions)):
                    action = legal_actions[index]
                    if action[0] == 'Bomb' and action[1] == 'JOKER':
                        return index
                return None

        if l > 20:
            tran_score['PASS'] = 30
        elif l >15:
            tran_score['PASS'] = 60
        else:
            tran_score['PASS'] = 1000

        max_s = 99999999
        ans = 0
        '''for i in range(18):
            print(i,end='  ')
        print()
        print(self.rough)'''
        if bucket_id == -1:
            if teammate:
                team_type, team_rank, team_cards = teammate_cards
                if team_type == 'Bomb' or team_type == 'StraightFlush':
                    tran_score['PASS'] = 0
                elif team_type == 'Straight':
                    team_rank = self.tran[team_rank]
                    if team_rank >= 5:

                        tran_score['PASS'] = 0
                elif team_type == 'TwoTrips' or team_type == 'ThreePair':
                    team_rank = self.tran[team_rank]
                    if team_rank > 7:
                        tran_score['PASS'] = 0
                else:
                    team_rank = self.tran[team_rank]
                    if team_rank > 10:
                        tran_score['PASS'] = 0

        hand_card = my_utils.cards2array(msg['handCards'], current_rank, only_card=True)
        for i in range(self.act_range + 1):
            type, rank, cards_play = self.action[i]
            tmp_dict={}
            this_action_card = my_utils.cards2array(cards_play, current_rank, only_card=True)
            left_card = hand_card - this_action_card
            if bucket_id != -1:
                if action_type != type or action_rank!=rank:
                    continue
            if rank == '':
                continue
            s = tran_score[type] + self.tran[rank]
            if type != 'PASS':
                for card in cards_play:
                    if self.tran[card[1]] not in tmp_dict:
                        tmp_dict[self.tran[card[1]]] = 1
                    else:
                        tmp_dict[self.tran[card[1]]] += 1
                for a in tmp_dict:
                    if a > 14:
                        continue
                    if tmp_dict[a] == self.rough[a]:
                        s -= 10
                    if self.rough[a] >=4 and self.rough[a] - tmp_dict[a] <4:
                        s += 20
                    if self.rough[a] - tmp_dict[a] == 1:
                        s += 10
                    elif self.rough[a] - tmp_dict[a] == 2:
                        s += 5
                # straight_num = my_utils.count_straight(left_card,0)
                for rank_index in range(13):
                    if left_card[rank_index] + left_card[-1] >=4:
                        if left_card.sum() - left_card[rank_index] - left_card[-1] == 0:
                            return i
            # print(self.action[i],s)
            if s < max_s:
                ans = i
                max_s = s
        return ans

    def read(self, cards):
        for card in cards:
            card_suit = card[0]
            card_rank = card[1]
            if card_rank == self.curRank and card_suit == 'H':
                self.all_match += 1
            self.rough[self.tran[card_rank]] += 1

        if self.all_match > 0:
            for i in range(18):
                if self.rough[i] == 3:
                    self.rough[i] += 1
                    self.all_match -= 1
                    break

