package com.wizzardo.epoll;

import com.wizzardo.epoll.readable.ReadableByteArray;
import com.wizzardo.epoll.readable.ReadableBytes;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author: wizzardo
 * Date: 1/6/14
 */
public class Connection<T extends EpollCore> {
    protected final int fd;
    protected final int ip, port;
    protected volatile Queue<ReadableBytes> sending;
    protected T epoll;
    private String ipString;
    private long lastEvent;
    private volatile boolean alive = true;

    public Connection(T epoll, int fd, int ip, int port) {
        this.fd = fd;
        this.ip = ip;
        this.port = port;
        this.epoll = epoll;
    }

    public String getIp() {
        if (ipString == null)
            ipString = getIp(ip);
        return ipString;
    }

    void setIpString(String ip) {
        ipString = ip;
    }

    private String getIp(int ip) {
        StringBuilder sb = new StringBuilder();
        sb.append((ip >> 24) + (ip < 0 ? 256 : 0)).append(".");
        sb.append((ip & 16777215) >> 16).append(".");
        sb.append((ip & 65535) >> 8).append(".");
        sb.append(ip & 255);
        return sb.toString();
    }

    public int getPort() {
        return port;
    }

    void setLastEvent(long lastEvent) {
        this.lastEvent = lastEvent;
    }

    long getLastEvent() {
        return lastEvent;
    }

    public boolean isAlive() {
        return alive;
    }

    void setIsAlive(boolean isAlive) {
        alive = isAlive;
    }

    public void write(String s) {
        try {
            write(s.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public void write(byte[] bytes) {
        write(bytes, 0, bytes.length);
    }

    public void write(byte[] bytes, int offset, int length) {
        write(new ReadableByteArray(bytes, offset, length));
    }

    public void write(ReadableBytes readable) {
        if (sending == null)
            synchronized (this) {
                if (sending == null)
                    sending = new ConcurrentLinkedQueue<ReadableBytes>();
            }

        sending.add(readable);
        write();
    }

    public void write() {
        if (sending == null)
            return;

        synchronized (this) {
            ReadableBytes readable;
            try {
                while ((readable = sending.peek()) != null) {
                    while (!readable.isComplete() && epoll.write(this, readable) > 0) {
                    }
                    if (!readable.isComplete()) {
                        epoll.startWriting(this);
                        return;
                    }

                    sending.poll();
                }
            } catch (Exception e) {
                e.printStackTrace();
                epoll.close(this);
            }

            epoll.stopWriting(this);
        }

    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Connection that = (Connection) o;

        if (fd != that.fd) return false;
        if (ip != that.ip) return false;
        if (port != that.port) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = fd;
        result = 31 * result + ip;
        result = 31 * result + port;
        return result;
    }

    @Override
    public String toString() {
        return fd + " " + getIp() + ":" + port;
    }

    public int read(byte[] bytes, int offset, int length) throws IOException {
        return epoll.read(this, bytes, offset, length);
    }
}

@@ -3644,32 +3644,139 @@
  + port;%0A    %7D%0A%0A
+    public int read(byte%5B%5D bytes) throws IOException %7B%0A        return read(bytes, 0, bytes.length);%0A    %7D%0A%0A
     public int r

add read(byte[])