from collections import defaultdict
from recorder import Recorder
from utils import Rank, Divisions
from constants import PASS, WEIGHT
from random import choice


class CardType(object):

    def __init__(self):
        self.rank = None
        self.type = None
        self.cards = None

    # 获得卡片类型等
    def analysis(self, data):
        if data is not None:
            self.rank = data["rank"]
            self.type = data["type"]
            self.cards = data["action"]


# 信息处理类
class MSGHandler(object):

    def __init__(self):
        self.index = None
        self.rest = [-1, -1, -1, -1]
        self.hand_cards = []
        self.teammate = None
        self.rank_obj = Rank()
        self.recorder = Recorder()

        self.ap = CardType()           # action_performed
        self.rank = '2'                # self rank
        self.op_rank = '2'             # opponent rank
        self.current_index = None      # index of current player
        self.current_stage = None      # current stage
        self.current_times = None      # current training times
        self.training_times = None     # total training times

        self.current_player = 0             # 当前出牌玩家
        self.greater_player = None

    # 根据收到的信息处理
    def handle(self, data):
        if data["type"] == 0:
            a = WEIGHT.card_map[data["current_rank"]]
            print("time_now", data["current_times"])
            WEIGHT.update(a)
            return self.episode_over(data)

        if data["action_performed"] and data["action_performed"]["type"] != "PASS":
            self.greater_player = self.current_player
        self.current_player = (self.current_player + 1) % 4

        if data["type"] == 1:
            return self.update(data)
        else:
            return self.decide(data)

    # 总结信息
    def episode_over(self, data):
        self.rank = data["self_rank"]
        self.op_rank = data["opponent_rank"]
        self.recorder.update_winners(data["winners"])
        self.rank_obj.update(data["current_rank"])
        self.current_times = data["current_times"]
        self.training_times = data["training_times"]

    # 更新已知信息
    def update(self, data):
        self.hand_cards = data["hand_cards"]
        self.index = data["index"]
        self.current_stage = data["current_stage"]
        self.current_index = data["current_player"]
        self.ap.analysis(data["action_performed"])
        self.recorder.update_cards(self.current_index, self.ap)
        for index, player_info in enumerate(data["public"]):
            self.rest[index] = player_info["rest"]
            # self.play_area[index] = player_info["play_area"]

    # 出牌
    def decide(self, data):
        self.update(data)

        # 决策集
        divisions = []
        # 动作空间
        action_space = []

        for card_type, card_list in data["action_list"].items():
            for rank, cards in card_list.items():
                for _card in cards:
                    # 找到一种卡牌组合
                    action_space.append(_card)
                    divisions.append(Divisions(_card, card_type, rank))

        # 关联度
        weight_table = defaultdict(int)
        # 遍历自己的每一个手牌，统计该牌有多少个在该手牌内
        for card in self.hand_cards:
            for act in action_space:
                if card in act:
                    weight_table[tuple(card)] += 1

        # 计算牌权值
        actions = []
        for division in divisions:
            actions.append((division, division.run(weight_table)))

        actions = min(actions, key=lambda x: x[1])

        # 对家没出牌并且有人出牌
        if self.greater_player != self.current_player or self.greater_player != (self.current_player+2) % 2:
            print("attract action")
            result = {"action": actions[0].cards, "type": actions[0].card_type, "rank": actions[0].rank}
        else:
            print("protect action")
            if actions[1] > WEIGHT.standard and actions[0].card_type != "PASS" and\
                    self.greater_player and self.greater_player != self.current_player:
                result = PASS
            else:
                result = {"action": actions[0].cards, "type": actions[0].card_type, "rank": actions[0].rank}

        print(result)
        return result

