package com.jscape.util.net;

import com.jscape.util.SuppressObfuscation;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.UnknownHostException;

/**
 * @author Alex Usun
 */
@SuppressObfuscation
public class TransportAddress
        implements Serializable {

    private InetAddress inetAddress;
    private String host;
    private int port;

    public static TransportAddress forUrl(URL url) {
        int port = url.getPort();
        if (port == -1) {
            port = "http".equalsIgnoreCase(url.getProtocol()) ? 80 : "https".equalsIgnoreCase(url.getProtocol()) ? 443 : 0;
        }

        return new TransportAddress(url.getHost(), port);
    }

    private TransportAddress(InetAddress inetAddress, String host, int port) {
        this.inetAddress = inetAddress;
        this.host = host;
        this.port = port;
    }

    public TransportAddress(String host, int port) {
        this(null, host, port);
    }

    public TransportAddress(InetAddress host, int port) {
        this(host, host != null ? host.getHostAddress() : null, port);
    }

    public TransportAddress(InetSocketAddress address) {
        this(address.getAddress(), address.getHostName(), address.getPort());
    }

    public TransportAddress(TransportAddress that) {
        this(that.inetAddress, that.host, that.port);
    }

    public TransportAddress() {
        // empty
    }

    public String getHost() {
        return this.host;
    }

    public void setHost(String value) {
        this.host = value;
    }

    public int getPort() {
        return this.port;
    }

    public void setPort(int value) {
        this.port = value;
    }

    public String hostName() {
        try {
            return inetAddress().getHostName();
        } catch (Exception e) {
            return this.host;
        }
    }

    public InetAddress inetAddress()
            throws UnknownHostException {
        return this.inetAddress != null ? this.inetAddress : InetAddress.getByName(this.host);
    }

    public TransportAddress domainAddress()
            throws UnknownHostException {
        return new TransportAddress(inetAddress().getHostName(), this.port);
    }

    public TransportAddress ipAddress()
            throws UnknownHostException {
        return new TransportAddress(inetAddress(), this.port);
    }

    public InetSocketAddress asSocketAddress() {
        return this.inetAddress != null ? new InetSocketAddress(this.inetAddress, this.port) : new InetSocketAddress(this.host, this.port);
    }

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

        TransportAddress that = (TransportAddress) o;

        if (this.port != that.port) {
            return false;
        }

        if (this.inetAddress != null && that.inetAddress != null) {
            return this.inetAddress.equals(that.inetAddress);
        }

        return NetTools.sameHost(this.host, that.host);
    }

    public int hashCode() {
        int result;
        result = this.host.hashCode();
        result = 31 * result + this.port;

        return result;
    }

    @Override
    public String toString() {
        return String.format("%s:%s", this.host, this.port);
    }
}
