using System.Collections;
using System.Collections.Generic;
using System.Net;
using System;

using NeonTea.Quakeball.TeaNet.Packets;

namespace NeonTea.Quakeball.TeaNet.Peers {
    /// <summary>Represents a connection to a remot host over the internet.</summary>
    public class Connection {

        /// <summary>The IP end point of the connection</summary>
        public IPEndPoint Endpoint;
        /// <summary>The unique identifier of the connection.</summary>
        public ulong uid;
        /// <summary>Connection status of the current connection.</summary>
        public ConnectionStatus Status;
        /// <summary>Reason why the connection closed. Null if no reason.</summary>
        public ClosingReason ClosingReason;

        /// <summary>Internal data for the connection. Do not touch, unless you know what you're doing.</summary>
        public ConnectionInternalData Internal = new ConnectionInternalData();

        public Connection(IPEndPoint endpoint, ConnectionStatus status = ConnectionStatus.Establishing) {
            Endpoint = endpoint;
            Status = status;

            Internal.LastMessage = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            Internal.LatestInwardReliable = -1;
            Internal.LatestInwardUnreliable = -1;
            Internal.LatestOutwardReliable = -1;
            Internal.LatestOutwardUnreliable = -1;
        }

        /// <summary>Is the connection ready and established for sending packets.</summary>
        public bool IsReady() {
            return Status == ConnectionStatus.Ready;
        }

        /// <summary>Is the connection disconnected. Shorthand for weather Status is Rejected, Closed, Stopped or Lost.</summary>
        public bool IsDisconnected() {
            return !(Status == ConnectionStatus.Ready
                || Status == ConnectionStatus.Awaiting
                || Status == ConnectionStatus.Establishing);
        }
    }

    public struct ConnectionInternalData {
        /// <summary>The protocol identifier, which this connection uses.</summary>
        public byte AssignedProtocol;
        /// <summary>Last unix timestamp in milliseconds, when this connection was last heard of.</summary>
        public long LastMessage;
        /// <summary>Last reliable Packet ID the connection has told us they have</summary>
        public int LatestOutwardReliable;
        /// <summary>Last unreliablePacket ID the connection has told us they have</summary>
        public int LatestOutwardUnreliable;
        /// <summary>Last reliable Packet ID we've received from the connection</summary>
        public int LatestInwardReliable;
        /// <summary>Last unreliable Packet ID we've received from the connection</summary>
        public int LatestInwardUnreliable;

        /// <summary>Reliable Packet ID counter for packets we're sending them</summary>
        public int ReliablePacketIDCounter;
        /// <summary>Unreliable Packet ID counter for packets we're sending them</summary>
        public int UnreliablePacketIDCounter;
    }

    /// <summary>Initiali</summary>
    public enum ConnectionStatus {
        /// <summary>Awaiting the other endpoint to establish the connection.</summary>
        Awaiting,
        /// <summary>Attempting to establish the connection.</summary>
        Establishing,
        /// <summary>Ready for packet sending</summary>
        Ready,
        /// <summary>Rejected connection at endpoint, sending information that it was rejected.</summary>
        Rejected,
        /// <summary>Closed the endpoint, and informing the connection that it should stop.</summary>
        Closed,
        /// <summary>Connection is stopped and waiting for timeout.</summary>
        Stopped,
        /// <summary>Connection Lost</summary>
        Lost,
    }
}
