
package com.googlecode.android_scripting.facade.wifi;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcParameter;
import com.googlecode.android_scripting.rpc.RpcOptional;

/**
 * Basic http operations.
 */
public class HttpFacade extends RpcReceiver {

    private ServerSocket mServerSocket = null;
    private int mServerTimeout = -1;
    private HashMap<Integer, Socket> mSockets = null;
    private int socketCnt = 0;

    public HttpFacade(FacadeManager manager) throws IOException {
        super(manager);
        mSockets = new HashMap<Integer, Socket>();
    }

    private void inputStreamToOutputStream(InputStream in, OutputStream out) throws IOException {
        if (in == null) {
            Log.e("InputStream is null.");
            return;
        }
        if (out == null) {
            Log.e("OutputStream is null.");
            return;
        }
        try {
            int read = 0;
            byte[] bytes = new byte[1024];
            while ((read = in.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            in.close();
            out.close();
        }

    }

    private String inputStreamToString(InputStream in) throws IOException {
        BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        String str = null;
        while ((str = r.readLine()) != null) {
            sb.append(str);
        }
        return sb.toString();
    }

    /**
     * Send an http request and get the response.
     * 
     * @param url The url to send request to.
     * @return The HttpURLConnection object.
     * @throws IOException When request failed to go through with response code 200.
     */
    private HttpURLConnection httpRequest(String url) throws IOException {
        URL targetURL = new URL(url);
        HttpURLConnection urlConnection = null;
        try {
            urlConnection = (HttpURLConnection) targetURL.openConnection();
            urlConnection.connect();
        } catch (IOException e) {
            Log.e("Failed to open a connection to " + url);
            Log.e(e.toString());
            throw e;
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
        return urlConnection;
    }

    @Rpc(description = "Start waiting for a connection request on a specified port.",
            returns = "The index of the connection.")
    public Integer httpAcceptConnection(Integer port) throws IOException {
        mServerSocket = new ServerSocket(port);
        if (mServerTimeout > 0) {
            mServerSocket.setSoTimeout(mServerTimeout);
        }
        Socket sock = mServerSocket.accept();
        socketCnt += 1;
        mSockets.put(socketCnt, sock);
        return socketCnt;
    }

    @Rpc(description = "Download a file from specified url.")
    public void httpDownloadFile(String url) throws IOException {
        HttpURLConnection urlConnection = httpRequest(url);
        String filename = null;
        String contentDisposition = urlConnection.getHeaderField("Content-Disposition");
        // Try to figure out the name of the file being downloaded.
        // If the server returned a filename, use it.
        if (contentDisposition != null) {
            int idx = contentDisposition.toLowerCase().indexOf("filename");
            if (idx != -1) {
                filename = contentDisposition.substring(idx + 9);
                Log.d("Using name returned by server: " + filename);
            }
        }
        // If the server did not provide a filename to us, use the last part of url.
        if (filename == null) {
            int lastIdx = url.lastIndexOf('/');
            filename = url.substring(lastIdx + 1);
            Log.d("Using name from url: " + filename);
        }
        InputStream in = new BufferedInputStream(urlConnection.getInputStream());
        String outPath = "/sdcard/Download/" + filename;
        OutputStream output = new FileOutputStream(new File(outPath));
        inputStreamToOutputStream(in, output);
        Log.d("Downloaded file at " + outPath);
    }

    @Rpc(description = "Make an http request and return the response message.")
    public HttpURLConnection httpPing(@RpcParameter(name = "url") String url) throws IOException {
        try {
            HttpURLConnection urlConnection = null;
            urlConnection = httpRequest(url);
            return urlConnection;
        } catch (UnknownHostException e) {
            return null;
        }
    }

    @Rpc(description = "Make an http request and return the response content as a string.")
    public String httpRequestString(@RpcParameter(name = "url") String url) throws IOException {
        HttpURLConnection urlConnection = httpRequest(url);
        InputStream in = new BufferedInputStream(urlConnection.getInputStream());
        String result = inputStreamToString(in);
        Log.d("Fetched: " + result);
        return result;
    }

    @Rpc(description = "Set how many milliseconds to wait for an incoming connection.")
    public void httpSetServerTimeout(@RpcParameter(name = "timeout") Integer timeout)
            throws SocketException {
        mServerSocket.setSoTimeout(timeout);
        mServerTimeout = timeout;
    }

    @Rpc(description = "Ping to host(URL or IP), return success (true) or fail (false).")
    // The optional timeout parameter is in unit of second.
    public Boolean pingHost(@RpcParameter(name = "host") String hostString,
            @RpcParameter(name = "timeout") @RpcOptional Integer timeout) {
        try {
            String host;
            try {
                URL url = new URL(hostString);
                host = url.getHost();
            } catch (java.net.MalformedURLException e) {
                Log.d("hostString is not URL, it may be IP address.");
                host = hostString;
            }

            Log.d("Host:" + host);
            String pingCmdString = "ping -c 1 ";
            if (timeout != null) {
                pingCmdString = pingCmdString + "-W " + timeout + " ";
            }
            pingCmdString = pingCmdString + host;
            Log.d("Execute command: " + pingCmdString);
            Process p1 = java.lang.Runtime.getRuntime().exec(pingCmdString);
            int returnVal = p1.waitFor();
            boolean reachable = (returnVal == 0);
            Log.d("Ping return Value:" + returnVal);
            return reachable;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
        /*TODO see b/18899134 for more information.
        */
    }

    @Override
    public void shutdown() {
        for (int key : mSockets.keySet()) {
            Socket sock = mSockets.get(key);
            try {
                sock.close();
            } catch (IOException e) {
                Log.e("Failed to close socket " + key + " on port " + sock.getLocalPort());
                e.printStackTrace();
            }
        }
    }
}
