package org.wikiwebserver.util.connector;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.text.DecimalFormat;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class WikiMapConnectorTest {
    
    private static void putObject(URL url, Object obj) throws IOException {
        deliver("PUT", url, obj);
    }
    
    private static void postObject(URL url, Object obj) throws IOException {
        deliver("POST", url, obj);
    }
    
    private static void deliver(String method, URL url, Object obj) throws IOException {
        
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.setDoOutput(true);
        
        conn.setRequestProperty("Content-Type", "application/x-java-serialized-object"); 
        ObjectOutputStream oos = new ObjectOutputStream(conn.getOutputStream());
        oos.writeObject(obj);
        oos.close();
        
        int responseCode = conn.getResponseCode();
        if (responseCode / 100 != 2) {
            throw new IOException("Failed to " + method + " object: " + conn.getResponseMessage());
        }
    }
    
    private static Object getObject(URL url) throws Exception {
        return request("GET", url);
    }
    
    private static void deleteObject(URL url) throws Exception {
        request("DELETE", url);
    }    
    
    public static Object request(String method, URL url) throws Exception {
        
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.addRequestProperty("Accept", "application/x-java-serialized-object");
        
        int responseCode = conn.getResponseCode();
        if (responseCode / 100 != 2) {
            throw new IOException("Failed to " + method + " object: " + conn.getResponseMessage());
        }
        
        if (method.equals("GET")) {
            ObjectInputStream in = new ObjectInputStream(conn.getInputStream());        
            return in.readObject();
        }
        return null;
    }
	
    public static void main(String[] args) {
       
       relaxSSLSecurity();
       
       
       try {

           URL url = new URL("https://127.0.0.1:8081/WikiMap/Mikey");

           int iterations = 1000;        
           
           long startTime = System.nanoTime();
           for (int i=0; i<iterations; i++) {
               
               deleteObject(url);
               putObject(url, "Sean is cool");
               postObject(url, new Integer(i));
               getObject(url);
               
           }
           
           System.out.println("Raw Object time: " + getDuration(startTime));      
      
           
       } catch (Exception ex) {
           ex.printStackTrace();
       }
   }
   
   private static String getDuration(long startTime) {
       double seconds = ((double)System.nanoTime() - startTime) / 1000000000;
       DecimalFormat df = new DecimalFormat("0.000");
       return df.format(seconds);
   }
   
   private static void relaxSSLSecurity() {
       
       // Create a trust manager that does not validate certificate chains
       TrustManager[] trustAllCerts = new TrustManager[]{
           new X509TrustManager() {
               public X509Certificate[] getAcceptedIssuers() {  return null; }
               public void checkClientTrusted(X509Certificate[] certs, String authType) {}
               public void checkServerTrusted(X509Certificate[] certs, String authType) {}
           }
       };
       
       // Install the all-trusting trust manager
       try {
           SSLContext sc = SSLContext.getInstance("SSL");
           sc.init(null, trustAllCerts, new SecureRandom());
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
       } catch (Exception e) {
           e.printStackTrace();
       }
       
       // Install the all-trusting host name verifier
       HostnameVerifier hostNameVerifier = new HostnameVerifier() {
           public boolean verify(String urlHostName, SSLSession session) {
               return true;
           }
       };
       HttpsURLConnection.setDefaultHostnameVerifier(hostNameVerifier);       
   }
   
}
