package de.lcs.wep.rest;

import de.lcs.wep.rest.tools.Validate;
import org.apache.commons.codec.binary.Base64;

/**
 * Created by Sönke Greve on 20.10.2014.
 */
public abstract class AClient {

    private String host;
    private int port;
    private String user;
    private String password;
    private boolean isAuthenticationRequired;

    /**
     * Creates a REST Client that can send WeP <i>(Wireless ePaper)</i> specific REST Requests to a defined HTTP Server.
     *
     * @param host the hostname or ip of the server to be requested, e.g. 'wep-server.com' or '10.86.2.20'
     * @param port the port the http server is listening on (usually 80)
     */
    public AClient(String host, int port) {
        setValidatedHost(host);
        this.port = port;
        this.isAuthenticationRequired = false;
    }

    /**
     * Creates a REST Client that can send WeP <i>(Wireless ePaper)</i> specific REST Requests to a defined HTTP Server.
     *
     * @param host     the hostname or ip of the server to be requested, e.g. 'wep-server.com' or '10.86.2.20'
     * @param port     the port the http server is listening on (usually 80)
     * @param user     the username that is sent in a request header when the server requires an authorization
     * @param password the password that is sent in a request header when the server requires an authorization
     * @see #setAuthenticationRequired(boolean)
     */
    public AClient(String host, int port, String user, String password) {
        this.host = host;
        this.port = port;
        this.user = user;
        this.password = password;
        this.isAuthenticationRequired = true;
    }

    /**
     * Defines if the server requires authentication credentials to be sent. Set this field to true in order to send an
     * authorization header generated from the username an password fields of this this instance.
     *
     * @param isAuthenticationRequired the flag defining if the server requires an authentication header to be sent
     */
    public void setAuthenticationRequired(boolean isAuthenticationRequired) {
        this.isAuthenticationRequired = isAuthenticationRequired;
    }

    /**
     * Defines if the server requires authentication credentials to be sent. Set this field to true in order to send an
     * authorization header generated from the username an password fields of this this instance.
     *
     * @return if true server requires an authentication header to be sent, false otherwise
     */
    public boolean isAuthenticationRequired() {
        return isAuthenticationRequired;
    }

    /**
     * Checks if the passed hostname is a valid domain name or ip and sets it to the 'host' field. If the hostname is not
     * valid an IllegalArgumentException is thrown.
     *
     * @param host the hostname to be checked
     * @throws IllegalArgumentException
     */
    private void setValidatedHost(String host) throws IllegalArgumentException {
        if (Validate.isValidDomainName(host) || Validate.isValidIP(host)) {
            this.host = host;
        } else {
            throw new IllegalArgumentException("The parameter provided is no valid host name or IP");
        }
    }

    /**
     * @return the authentication value String to be passed in the request header in case authentication is required
     * @see #setUser(String)
     * @see #setPassword(String)
     */
    public String buildBasicAuthString() {
        String auth = user + ":" + password;
        byte[] authEncBytes = Base64.encodeBase64(auth.getBytes());
        String result = "Basic " + new String(authEncBytes);
        return result;
    }

    /**
     * @return the hostname or ip of the server to be requested, e.g. 'wep-server.com' or '10.86.2.20'
     */
    public String getHost() {
        return host;
    }

    /**
     * @param host the hostname or ip of the server to be requested, e.g. 'wep-server.com' or '10.86.2.20'
     */
    public void setHost(String host) {
        this.host = host;
    }

    /**
     * @return the port the http server is listening on (usually 80)
     */
    public int getPort() {
        return port;
    }

    /**
     * @param port the port the http server is listening on (usually 80)
     */
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * @param user the username that is sent in a request header when the server requires an authorization
     */
    public void setUser(String user) {
        this.user = user;
    }

    /**
     * @return the username that is sent in a request header when the server requires an authorization
     */
    public String getUser() {
        return user;
    }

    /**
     * @param password the password that is sent in a request header when the server requires an authorization
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @return the password that is sent in a request header when the server requires an authorization
     */
    public String getPassword() {
        return password;
    }

}
