use common::net::tools::Packet;
use proto::{ChangeAvatarRsp, Retcode, SetUpAvatarTeamRsp};

use crate::player::Player;

use super::get_proto;
use std::{error::Error, rc::Rc};

pub fn on_set_up_avatar_team_req(
    player: &Rc<Player>,
    packet: Packet,
) -> Result<(), Box<dyn Error>> {
    let req = get_proto!(packet, SetUpAvatarTeamReq);
    let mut rsp = SetUpAvatarTeamRsp {
        avatar_team_guid_list: req.avatar_team_guid_list.clone(),
        team_id: req.team_id,
        cur_avatar_guid: req.cur_avatar_guid,
        retcode: Retcode::RetSucc.into(),
    };

    if req.avatar_team_guid_list.len() <= 4 {
        if let Err(ret) = player.check_is_in_safe_state_for_change_team() {
            rsp.retcode = ret.into();
            tracing::info!(
                "SetUpAvatarTeam fails, not in safe state, uid:{}, ret:{ret:?}",
                player.uid
            );
        } else {
            if player
                .player_avatar_comp
                .borrow()
                .check_avatar_guid_vec_all_formal(&req.avatar_team_guid_list)
                .is_ok()
            {
                let avatar_comp = player.player_avatar_comp.borrow();
                if let Err(ret) = avatar_comp.set_up_avatar_team(
                    req.team_id,
                    &req.avatar_team_guid_list,
                    req.cur_avatar_guid,
                ) {
                    tracing::info!("set_up_avatar_team fails, uid:{}", player.uid);
                    rsp.retcode = ret.into();
                }
            } else {
                rsp.retcode = Retcode::RetFail.into();
                tracing::info!("checkAvatarTeamAllFormal failed");
            }
        }
    } else {
        tracing::warn!(
            "avatar_guid_list_size too large:{}",
            req.avatar_team_guid_list.len()
        );
        rsp.retcode = Retcode::RetFail.into();
    }

    player.send_proto(rsp);
    Ok(())
}

pub fn on_change_avatar_req(player: &Rc<Player>, packet: Packet) -> Result<(), Box<dyn Error>> {
    let req = get_proto!(packet, ChangeAvatarReq);
    let mut rsp = ChangeAvatarRsp::default();

    if player.player_scene_comp.borrow().get_dest_scene().is_some() {
        tracing::info!("intransfer cannot choose cur avatar team.");
        rsp.retcode = Retcode::RetAvatarNotOnScene.into();
        player.send_proto(rsp);
        return Ok(());
    }

    rsp.cur_guid = req.guid;
    rsp.skill_id = req.skill_id;

    if req.guid != 0 {
        if player
            .player_avatar_comp
            .borrow()
            .is_my_avatar_in_scene_team(req.guid)
        {
            let cur_guid = {
                let cur_avatar_ptr = player.player_avatar_comp.borrow().get_cur_avatar().unwrap();
                let cur_avatar = cur_avatar_ptr.borrow();
                cur_avatar.base_avatar().guid
            };

            if req.guid == cur_guid {
                rsp.retcode = Retcode::RetSucc.into();
            } else {
                let avatar_comp = player.player_avatar_comp.borrow();
                if let Err(ret) = avatar_comp.check_change_cur_avatar(req.guid) {
                    tracing::info!("check_change_cur_avatar ret:{ret:?}, guid:{}", req.guid);
                    rsp.retcode = ret.into();
                } else {
                    if req.is_move {
                        // TODO!
                    }

                    let _ = avatar_comp.change_cur_avatar(req.guid, true);
                    rsp.retcode = Retcode::RetSucc.into();
                }
            }
        } else {
            tracing::info!(
                "avatar not in cur team, player:{} guid:{}",
                player.uid,
                req.guid
            );
            rsp.retcode = Retcode::RetAvatarNotExistInTeam.into();
        }
    } else {
        tracing::warn!("guid != 0 !!! player:{}", player.uid);
        rsp.retcode = Retcode::RetFail.into();
    }

    Ok(())
}
