#nullable enable
using System;
using System.Collections.Generic;

namespace IGP.UnitySDK.Network
{
    /// <summary>
    /// 玩家的唯一标识
    /// </summary>
    [Serializable]
    public struct IGPPlayerID : IEquatable<IGPPlayerID>
    {
        public string id;

        public IGPPlayerID(string id)
        {
            this.id = id;
        }

        public static implicit operator string(IGPPlayerID playerID)
        {
            return playerID.id;
        }

        public static implicit operator IGPPlayerID(string id)
        {
            return new IGPPlayerID(id);
        }

        public override string ToString()
        {
            return id;
        }

        public bool Equals(IGPPlayerID other)
        {
            return id == other.id;
        }

        public override bool Equals(object? obj)
        {
            return obj is IGPPlayerID other && Equals(other);
        }

        public override int GetHashCode()
        {
            return id != null ? id.GetHashCode() : 0;
        }

        public static bool operator ==(IGPPlayerID left, IGPPlayerID right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(IGPPlayerID left, IGPPlayerID right)
        {
            return !left.Equals(right);
        }
    }

    /// <summary>
    /// 游戏的唯一标识
    /// </summary>
    [Serializable]
    public struct IGPGameID : IEquatable<IGPGameID>
    {
        public string id;

        public IGPGameID(string id)
        {
            this.id = id;
        }
        
        public static implicit operator string(IGPGameID gameID)
        {
            return gameID.id;
        }

        public static implicit operator IGPGameID(string id)
        {
            return new IGPGameID(id);
        }

        public bool Equals(IGPGameID other)
        {
            return id == other.id;
        }
    }

    /// <summary>
    /// 远程玩家信息，包括用户id、所在游戏id
    /// </summary>
    [Serializable]
    public struct IGPGamePeer
    {
        public IGPPlayerID player_id;
        public IGPGameID game_id;
        
        public IGPGamePeer(IGPPlayerID playerId, IGPGameID gameId)
        {
            this.player_id = playerId;
            this.game_id = gameId;
        }
    }

    /// <summary>
    /// 网络操作结果
    /// </summary>
    public enum IGPNetworkResult
    {
        kSuccess = 0,
        kErrorUnknown = 1,
        kErrorInvalidParam = 2,
        kErrorInvalidState = 3,
        kErrorServiceNotAvailable = 4,
        kErrorNetworkUnReachable = 5,
        kErrorNetworkRemotePeerOffline = 6,
        kErrorNetworkServerUnavailable = 7,
        kErrorNetworkConnectionDenied = 8,
        kErrorNetworkConnectionClosed = 9,
        kErrorNetworkConnectionReset = 10,
        kErrorNetworkError = 11
    }

    /// <summary>
    /// 会话状态
    /// </summary>
    public struct IGPNetworkSessionState
    {
        public IGPPlayerID remote_peer;
        public bool is_connected;
        public bool is_writable;
        public uint packets_in_flight;
        public uint bytes_in_flight;
    }
    
    // 事件回调委托定义
    
    [Serializable]
    public class IGPSessionRequestEvent : UnityEngine.Events.UnityEvent<CreateSessionRequest> { }

    [Serializable]
    public class IGPSessionFailedEvent : UnityEngine.Events.UnityEvent<CreateSessionFailed> { }

    [Serializable]
    public class IGPRawSessionRequestEvent : UnityEngine.Events.UnityEvent<NetworkCreateRawSessionRequest> { }

    [Serializable]
    public class IGPRawSessionFailedEvent : UnityEngine.Events.UnityEvent<NetworkCreateRawSessionFailed> { }

    [Serializable]
    public class IGPDataReceived
    {
        public IGPPlayerID remote_peer;
        public byte[] data = Array.Empty<byte>();
        public uint message_type;
    }

    [Serializable]
    public class IGPDataReceivedEvent : UnityEngine.Events.UnityEvent<IGPDataReceived> { }

    [Serializable]
    public class P2PMessagePayload
    {
        public string senderId = string.Empty;
        public string targetId = string.Empty;
        public string data = string.Empty; // Base64
        public uint messageType;
        public bool reliable; // KCP p2p_data 统一按可靠处理；字段保留给兼容和分片元数据。
        public string? reliableMessageId;
        public int? reliableChunkIndex;
        public int? reliableChunkCount;
        public int? reliableTotalBytes;
        public uint? reliableMessageType;
    }

    public delegate void CreateSessionRequestCallback(CreateSessionRequest data);
    public delegate void CreateSessionFailedCallback(CreateSessionFailed data);
    public delegate void NetworkCreateRawSessionRequestCallback(NetworkCreateRawSessionRequest data);
    public delegate void NetworkCreateRawSessionFailedCallback(NetworkCreateRawSessionFailed data);

    [Serializable]
    public class CreateSessionRequest
    {
        public IGPPlayerID local_peer;
        public IGPPlayerID remote_peer;
        public string user_data = string.Empty;
    }

    [Serializable]
    public class CreateSessionFailed
    {
        public IGPPlayerID local_peer;
        public IGPPlayerID remote_peer;
        public IGPNetworkResult result;
        public string user_data = string.Empty;
    }

    [Serializable]
    public class NetworkCreateRawSessionRequest
    {
        public IGPPlayerID local_peer;
        public IGPGamePeer remote_game_peer;
        public string user_data = string.Empty;
    }

    [Serializable]
    public class NetworkCreateRawSessionFailed
    {
        public IGPPlayerID local_peer;
        public IGPGamePeer remote_game_peer;
        public IGPNetworkResult result;
        public string user_data = string.Empty;
    }
}
