// Generated by delombok at Tue Dec 16 19:36:13 UTC 2025
package net.md_5.bungee;

import com.google.common.base.Preconditions;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayDeque;
import java.util.Queue;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.PluginMessage;

public class ServerConnection implements Server {
    private final ChannelWrapper ch;
    private final BungeeServerInfo info;
    private boolean isObsolete;
    private final boolean forgeServer = false;
    private final Queue<KeepAliveData> keepAlives = new ArrayDeque<>();
    private final Queue<DefinedPacket> packetQueue = new ArrayDeque<>();
    private final Unsafe unsafe = new Unsafe() {
        @Override
        public void sendPacket(DefinedPacket packet) {
            ch.write(packet);
        }
        @Override
        public void sendPacketQueued(DefinedPacket packet) {
            if (ch.getEncodeVersion() >= ProtocolConstants.MINECRAFT_1_20_2) {
                ServerConnection.this.sendPacketQueued(packet);
            } else {
                sendPacket(packet);
            }
        }
    };

    public void sendPacketQueued(DefinedPacket packet) {
        ch.scheduleIfNecessary(() -> {
            if (ch.isClosed()) {
                return;
            }
            Protocol encodeProtocol = ch.getEncodeProtocol();
            if (!encodeProtocol.TO_SERVER.hasPacket(packet.getClass(), ch.getEncodeVersion())) {
                // we should limit this so bad api usage won't oom the server.
                Preconditions.checkState(packetQueue.size() <= 4096, "too many queued packets");
                packetQueue.add(packet);
            } else {
                unsafe().sendPacket(packet);
            }
        });
    }

    public void sendQueuedPackets() {
        ch.scheduleIfNecessary(() -> {
            if (ch.isClosed()) {
                return;
            }
            DefinedPacket packet;
            while ((packet = packetQueue.poll()) != null) {
                unsafe().sendPacket(packet);
            }
        });
    }

    @Override
    public void sendData(String channel, byte[] data) {
        sendPacketQueued(new PluginMessage(channel, data, forgeServer));
    }

    @Override
    public void disconnect(String reason) {
        disconnect();
    }

    @Override
    public void disconnect(BaseComponent... reason) {
        Preconditions.checkArgument(reason.length == 0, "Server cannot have disconnect reason");
        isObsolete = true;
        ch.close();
    }

    @Override
    public void disconnect(BaseComponent reason) {
        disconnect();
    }

    @Override
    public InetSocketAddress getAddress() {
        return (InetSocketAddress) getSocketAddress();
    }

    @Override
    public SocketAddress getSocketAddress() {
        return getInfo().getAddress();
    }

    @Override
    public boolean isConnected() {
        return !ch.isClosed();
    }

    @Override
    public Unsafe unsafe() {
        return unsafe;
    }


    public static class KeepAliveData {
        private final long id;
        private final long time;

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public KeepAliveData(final long id, final long time) {
            this.id = id;
            this.time = time;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public long getId() {
            return this.id;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public long getTime() {
            return this.time;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public boolean equals(final java.lang.Object o) {
            if (o == this) return true;
            if (!(o instanceof ServerConnection.KeepAliveData)) return false;
            final ServerConnection.KeepAliveData other = (ServerConnection.KeepAliveData) o;
            if (!other.canEqual((java.lang.Object) this)) return false;
            if (this.getId() != other.getId()) return false;
            if (this.getTime() != other.getTime()) return false;
            return true;
        }

        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        protected boolean canEqual(final java.lang.Object other) {
            return other instanceof ServerConnection.KeepAliveData;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public int hashCode() {
            final int PRIME = 59;
            int result = 1;
            final long $id = this.getId();
            result = result * PRIME + (int) ($id >>> 32 ^ $id);
            final long $time = this.getTime();
            result = result * PRIME + (int) ($time >>> 32 ^ $time);
            return result;
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        @lombok.Generated
        public java.lang.String toString() {
            return "ServerConnection.KeepAliveData(id=" + this.getId() + ", time=" + this.getTime() + ")";
        }
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public ServerConnection(final ChannelWrapper ch, final BungeeServerInfo info) {
        this.ch = ch;
        this.info = info;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public ChannelWrapper getCh() {
        return this.ch;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public BungeeServerInfo getInfo() {
        return this.info;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public boolean isObsolete() {
        return this.isObsolete;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public void setObsolete(final boolean isObsolete) {
        this.isObsolete = isObsolete;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public boolean isForgeServer() {
        return this.forgeServer;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public Queue<KeepAliveData> getKeepAlives() {
        return this.keepAlives;
    }
}
