def get_meta_info_list(account: PlayerAccount):
    logger.info("[{}] get mail meta info".format(account.uid))
    data = META_INFO_DATA.copy()
    data["from"] = int(time.time())
    ret_data = http_client.post_with_seqnum(account, META_INFO_URL,
                                            data=json.dumps(data))
    return ret_data
def start_battle_replay(account: PlayerAccount, battle_type, stage_id):
    battle_type = BattleModel.BattleType.get_value_or_default(battle_type)
    api = BATTLE_START_URL.format(battle_type=battle_type)
    data = BATTLE_START_REPLAY_DATA.copy()
    mybattle = BattleModel.Battle(account, battle_type, stage_id)
    if not mybattle.has_battle_data():
        logger.error("[{}] battle reply data for stage id={} not found".format(
            account.uid, stage_id))
        return
    if account.current_battle.get(stage_id) is not None:
        logger.warning("[{}] already start battle for stage id={}".format(
            account.uid, stage_id))
        return
    logger.info("[{}] starting battle stage_id={}".format(
        account.uid, stage_id))
    data["stageId"] = stage_id
    # simulate system delay
    data["startTs"] = mybattle.start_time - 1
    ret_data = http_client.post_with_seqnum(account,
                                            api,
                                            data=json.dumps(data))
    if ret_data.get("battleId") is None:
        logger.warning("[{}] fail to start battle replay, reason: {}".format(
            account.uid, ret_data))
        return ret_data
    mybattle.battle_id = ret_data.get("battleId")
    account.current_battle[stage_id] = mybattle
    return ret_data
def get_all_intimacy(account: PlayerAccount):
    logger.info("[{}] getting all intimacy..".format(account.uid))
    ret_data = http_client.post_with_seqnum(
        account,
        GAIN_ALL_INTIMACY_URL,
        data=json.dumps(GAIN_ALL_INTIMACY_DATA))
    return ret_data
def get_current_friend(account: PlayerAccount):
    logger.info("[{}] get current friend list".format(account.uid))
    data = CURRENT_FRIEND_DATA.copy()
    ret_data = http_client.post_with_seqnum(account,
                                            SORT_LIST_URL,
                                            data=json.dumps(data))
    return ret_data
def confirm_mission(account: PlayerAccount, mission_id):
    logger.info("[{}] confirm mission id={}".format(account.uid, mission_id))
    data = CONFIRM_MISSION_DATA.copy()
    data["missionId"] = mission_id
    ret_data = http_client.post_with_seqnum(account,
                                            CONFIRM_MISSION_URL,
                                            data=json.dumps(data))
    return ret_data
def search_account(account: PlayerAccount, nickname="", nicknumber=""):
    logger.info("[{}] search friend with {}#{}".format(account.uid, nickname,
                                                       nicknumber))
    data = SEARCH_ACCOUNT_DATA.copy()
    data["param"] = {"nickName": nickname, "nickNumber": nicknumber}
    ret_data = http_client.post_with_seqnum(account,
                                            SORT_LIST_URL,
                                            data=json.dumps(data))
    return ret_data
def auto_confirm_missions_by_type(account: PlayerAccount, mission_type):
    logger.info("[{}] auto confirm {} missions".format(account.uid,
                                                       mission_type))
    data = AUTO_CONFIRM_MISSIONS_DATA.copy()
    data["type"] = mission_type
    ret_data = http_client.post_with_seqnum(account,
                                            AUTO_CONFIRM_MISSIONS_URL,
                                            data=json.dumps(data))
    return ret_data
def exchange_mission_reward(account: PlayerAccount, reward_id):
    logger.info("[{}] exchange mission reward id={}".format(
        account.uid, reward_id))
    data = EXCHANGE_MISSION_REWARDS_DATA.copy()
    data["targetRewardsId"] = reward_id
    ret_data = http_client.post_with_seqnum(account,
                                            EXCHANGE_MISSION_REWARDS_URL,
                                            data=json.dumps(data))
    return ret_data
def get_friend_info(account: PlayerAccount, *uids, uid_list=None):
    id_list = [] if uid_list == None else uid_list
    id_list.extend(list(uids))
    logger.info("[{}] get friend info for uid={}".format(account.uid, id_list))
    data = FRIEND_INFO_DATA.copy()
    data["idList"] = id_list
    ret_data = http_client.post_with_seqnum(account,
                                            FRIEND_INFO_URL,
                                            data=json.dumps(data))
    return ret_data
def receive_all_mail(account: PlayerAccount, *ids, id_list=None):
    id_list = [] if id_list == None else id_list
    id_list.extend(list(ids))
    logger.info("[{}] receive mail for id={}".format(account.uid, id_list))
    data = RECEIVE_ALL_MAIL_DATA.copy()
    # todo: temporary solution
    data["mailIdList"] = list(filter(lambda x: int(x) > 10000, id_list))
    data["sysMailIdList"] = list(filter(lambda x: int(x) <= 10000, id_list))
    ret_data = http_client.post_with_seqnum(account, RECEIVE_ALL_MAIL_URL,
                                            data=json.dumps(data))
    return ret_data
def search_player_info_by_uid(account: PlayerAccount, *uids, uid_list=None):
    id_list = [] if uid_list == None else uid_list
    id_list.extend(list(uids))
    logger.info("[{}] get search result for uid={}".format(
        account.uid, id_list))
    data = SEARCH_PLAYER_INFO_DATA.copy()
    data["idList"] = id_list
    ret_data = http_client.post_with_seqnum(account,
                                            SEARCH_PLAYER_INFO_URL,
                                            data=json.dumps(data))
    return ret_data
def list_mail_box(account: PlayerAccount, *ids, id_list=None):
    id_list = [] if id_list == None else id_list
    id_list.extend(list(ids))
    logger.info("[{}] get mail info for id={}".format(account.uid, id_list))
    data = LIST_MAILBOX_DATA.copy()
    #todo: temporary solution
    data["mailIdList"] = list(filter(lambda x:int(x)>10000,id_list))
    data["sysMailIdList"] = list(filter(lambda x:int(x)<=10000,id_list))
    ret_data = http_client.post_with_seqnum(account, LIST_MAILBOX_URL,
                                            data=json.dumps(data))
    return ret_data
def settle_manufacture(account: PlayerAccount, *ids, slot_ids=None):
    slot_ids = [] if slot_ids is None else slot_ids
    slot_ids.extend(ids)
    if len(slot_ids) == 0:
        slot_ids = [
            room.slot_id
            for room in BuildingModel.get_room_by_type(account, "MANUFACTURE")
        ]
    logger.info("[{}] settle manufacture for slot_ids={}".format(
        account.uid, slot_ids))
    data = SETTLE_MANUFACTURE_DATA.copy()
    data["roomSlotIdList"] = slot_ids
    ret_data = http_client.post_with_seqnum(account,
                                            SETTLE_MANUFACTURE_URL,
                                            data=json.dumps(data))
    return ret_data
def delivery_batch_order(account: PlayerAccount, *ids, slot_ids=None):
    slot_ids = [] if slot_ids is None else slot_ids
    slot_ids.extend(ids)
    if len(slot_ids) == 0:
        slot_ids = [
            room.slot_id
            for room in BuildingModel.get_room_by_type(account, "TRADING")
        ]
    logger.info("[{}] delivery batch order for slot_ids={}".format(
        account.uid, slot_ids))
    data = DELIVERY_BATCH_ORDER_DATA.copy()
    data["slotList"] = slot_ids
    ret_data = http_client.post_with_seqnum(account,
                                            DELIVERY_BATCH_ORDER_URL,
                                            data=json.dumps(data))
    return ret_data
def finish_battle(account: PlayerAccount, stage_id):
    mybattle: BattleModel.Battle = account.current_battle.get(stage_id)
    api = BATTLE_FINISH_URL.format(battle_type=mybattle.type)
    if mybattle is None:
        logger.warning(
            "[{}] battle for stage id={} is finished or not started".format(
                account.uid, stage_id))
    logger.info("[{}] finishing battle stage id={} battle_id={}".format(
        account.uid, stage_id, mybattle.battle_id))
    battle_data = mybattle.get_battle_data()
    data = BATTLE_FINISH_DATA.copy()
    data["data"] = battle_data
    data["battleData"]["completeTime"] = mybattle.complete_time
    data["battleData"]["isCheat"] = mybattle.is_cheat
    account.current_battle.pop(stage_id)
    ret_data = http_client.post_with_seqnum(account,
                                            api,
                                            data=json.dumps(data))
    return ret_data
def exchange_mission_reward_by_type(account: PlayerAccount, mission_type):
    mission_rewards = list(
        filter(
            lambda m: m.can_exchange(),
            mission_model.get_mission_rewards_by_type(account, mission_type)))
    logger.info("[{}] exchange mission reward type = {}, {} left".format(
        account.uid, mission_type, len(mission_rewards)))
    if len(mission_rewards) == 0:
        logger.info(
            "[{}] all mission rewards can be exchange have been exchanged".
            format(account.uid))
        return
    for mission_reward in mission_rewards:
        mission_reward: mission_model.MissionReward
        ret = exchange_mission_reward(account, mission_reward.id)
        if ret is None:
            logger.error(
                "[{}] stop exchange mission reward due to http connection error"
                .format(account.uid))
            return
        if ret.get("playerDataDelta") is None:
            logger.error(
                "[{}] stop exchange mission reward due to api error".format(
                    account.uid))
            return
    logger.info("[{}] try to exchange more mission".format(account.uid))
    exchange_mission_reward_by_type(account, mission_type)
def confirm_mission_by_type(account: PlayerAccount, mission_type):
    missions = list(
        filter(lambda m: m.can_confirm(),
               mission_model.get_mission_by_type(account, mission_type)))
    logger.info("[{}] confirming mission type = {}, {} left".format(
        account.uid, mission_type, len(missions)))
    if len(missions) == 0:
        logger.info(
            "[{}] all mission can be confirmed have been confirmed".format(
                account.uid))
        return
    for mission in missions:
        mission: mission_model.Mission
        ret = confirm_mission(account, mission.id)
        if ret is None:
            logger.error(
                "[{}] stop confirming mission due to http connection error".
                format(account.uid))
            return
        if ret.get("playerDataDelta") is None:
            logger.error(
                "[{}] stop confirming mission due to api error".format(
                    account.uid))
            return
    logger.info("[{}] try to get more mission".format(account.uid))
    confirm_mission_by_type(account, mission_type)
def receive_all_mail_with_item(account: PlayerAccount):
    logger.info("[{}] receive mail with item".format(account.username))
    meta_info = get_meta_info_list(account)
    if meta_info is None or len(meta_info) == 0:
        logger.info("[{}] no mail in the box or get mail fail".format(account.username))
        return
    id_list = [rs["mailId"] for rs in meta_info["result"]]
    mail_info = list_mail_box(account, id_list=id_list)
    if mail_info is None or len(mail_info) == 0:
        logger.info("[{}] no mail in the box or get mail fail".format(account.username))
        return
    valid_ids = []
    for mail in mail_info["mailList"]:
        if mail["hasItem"] == 1 and mail["state"] == 0:
            valid_ids.append(mail["mailId"])
    if len(valid_ids) == 0:
        logger.info("[{}] no mail need to be receive".format(account.username))
        return
    return receive_all_mail(account, id_list=valid_ids)
def checkin(account:PlayerAccount):
    logger.info("[{}] checkin".format(account.uid))
    ret_data = http_client.post_with_seqnum(account, CHECKIN_URL,
                                            data=json.dumps(CHECKIN_DATA))
    return ret_data
def sync_building(account: PlayerAccount):
    logger.info("[{}] sync building..".format(account.uid))
    ret_data = http_client.post_with_seqnum(
        account, BUILDING_SYNC_URL, data=json.dumps(BUILDING_SYNC_DATA))
    return ret_data