"""Pydantic models for protocol buffer message conversion."""
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
from datetime import datetime


class ProtoMessageBase(BaseModel):
    """Base class for protocol buffer message models."""
    message_type: str
    timestamp: datetime = datetime.now()


class SessionCommand(ProtoMessageBase):
    """Session command message."""
    message_type: str = "SessionCommand"
    cmd_type: int
    cmd_id: int = 0
    data: Dict[str, Any] = {}


class GameCommand(ProtoMessageBase):
    """Game command message."""
    message_type: str = "GameCommand"
    cmd_type: int
    cmd_id: int = 0
    player_id: Optional[int] = None
    data: Dict[str, Any] = {}


class GameEvent(ProtoMessageBase):
    """Game event message."""
    message_type: str = "GameEvent"
    event_type: int
    player_id: Optional[int] = None
    data: Dict[str, Any] = {}


class Response(ProtoMessageBase):
    """Response message."""
    message_type: str = "Response"
    cmd_id: int
    response_code: int
    data: Dict[str, Any] = {}


class ServerInfoUser(BaseModel):
    """ServerInfo_User message."""
    id: int
    name: str
    user_level: int = 0
    address: Optional[str] = None
    real_name: Optional[str] = None
    country: Optional[str] = None
    avatar_bmp: Optional[bytes] = None
    server_id: Optional[int] = None
    session_id: Optional[int] = None
    accountage_secs: Optional[int] = None
    email: Optional[str] = None
    privlevel: Optional[str] = None


class ServerInfoDeckStorageFile(BaseModel):
    """ServerInfo_DeckStorage_File message."""
    creation_time: Optional[int] = None


class ServerInfoDeckStorageFolder(BaseModel):
    """ServerInfo_DeckStorage_Folder message."""
    items: List[Dict[str, Any]] = []


class ServerInfoDeckStorageTreeItem(BaseModel):
    """ServerInfo_DeckStorage_TreeItem message."""
    id: Optional[int] = None
    name: Optional[str] = None
    file: Optional[ServerInfoDeckStorageFile] = None
    folder: Optional[ServerInfoDeckStorageFolder] = None


class ServerInfoCard(BaseModel):
    """ServerInfo_Card message."""
    id: int
    name: str
    x: Optional[int] = None
    y: Optional[int] = None
    face_down: bool = False
    tapped: bool = False
    attacking: bool = False
    color: Optional[str] = None
    pt: Optional[str] = None
    annotation: Optional[str] = None
    destroy_on_zone_change: bool = False
    doesnt_untap: bool = False
    counter_list: List[Dict[str, Any]] = []
    attach_player_id: Optional[int] = None
    attach_zone: Optional[str] = None
    attach_card_id: Optional[int] = None
    provider_id: Optional[str] = None


class ServerInfoZone(BaseModel):
    """ServerInfo_Zone message."""
    name: str
    zone_type: int = 0  # PrivateZone=0, PublicZone=1, HiddenZone=2
    with_coords: bool = False
    card_count: int = 0
    card_list: List[ServerInfoCard] = []
    always_reveal_top_card: bool = False
    always_look_at_top_card: bool = False


class ServerInfoGame(BaseModel):
    """ServerInfo_Game message."""
    server_id: Optional[int] = None
    room_id: Optional[int] = None
    game_id: Optional[int] = None
    description: Optional[str] = None
    with_password: bool = False
    max_players: int = 4
    game_types: List[int] = []
    creator_info: Optional[ServerInfoUser] = None
    only_buddies: bool = False
    only_registered: bool = False
    spectators_allowed: bool = False
    spectators_need_password: bool = False
    spectators_can_chat: bool = False
    spectators_omniscient: bool = False
    share_decklists_on_load: bool = False
    player_count: int = 0
    spectators_count: int = 0
    started: bool = False
    start_time: Optional[int] = None
    closed: bool = False
