package com.onset.test.rest.webservices;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;


public class OnsetRestWebserviceExample {

    public void getLatestDataFile() throws UniformInterfaceException {
        //create default client config
        ClientConfig config = new DefaultClientConfig();

        // --setup the SSL configuration--
        //create a hostname verifier
        HostnameVerifier hostnameVerifier = getHostnameVerifier();
        //create the ssl context
        SSLContext sslContext = getSSLContext();
        //create and populate the https properties with the hostname verifier and ssl context you created
        HTTPSProperties httpsProperties = new HTTPSProperties(hostnameVerifier, sslContext);
        config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, httpsProperties);

        //now that you have ssl configured, create a Client with the config you created
        Client client = Client.create(config);

        //create a username and password
        String username="joe_user";
        String password="my_password";


        //now create an HTTP Basic Authentication filter that holds the username and password
        HTTPBasicAuthFilter basicAuthenticationCredentials = new HTTPBasicAuthFilter(username, password);

        //pass the authentication credentials to the client object
        client.addFilter(basicAuthenticationCredentials);

        //create a web resource that points to the URL that you want
        WebResource webResource = client.resource("https://webservice.hobolink.com/rest/devices/1192491/data_files/latest/dtf");

        //call "get" on your web resource. You must provide the "GET" method with the class type that you expect to get back.
        //This could be different class types depending on the service URL you are calling. Some url's may return a String for example.
        //For this particular example, we know that the service is passing back a java File type.
        File file = webResource.get(File.class);
        //done, process the file as needed.
        saveFileToLocalFilesystem(file, "/Users/gmirabito/webServiceTest/dtf_file_from_rest_service.dtf");

        //change the a web resource to get a text file
        webResource = client.resource("https://webservice.hobolink.com/rest/private/devices/1192491/data_files/latest/txt");

        //this time, since we are requesting text data, we will get the data as a string. We could have used a file, but here I am demonstrating the
        //automatic type conversion of the library.
        String textFileData = webResource.get(String.class);
        System.out.println("text file data = " + textFileData);

        //now i will make the same web service call, but instead if getting a string back, I will get the result as a file.
        //The only change here is that I pass the "GET" method a File.class instead of a String.class
        File textFile = webResource.get(File.class);
        saveFileToLocalFilesystem(textFile,"/Users/gmirabito/webServiceTest/text_file_from_rest_service.txt");


    }


    private void saveFileToLocalFilesystem(File file, String saveFileAs){
        try{
            FileOutputStream os = new FileOutputStream(saveFileAs);
            FileInputStream is = new FileInputStream(file);
            byte[] fileBytes = new byte[(int)file.length()];
            os.write(is.read(fileBytes));
            os.flush();
            os.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    //This is how the ssl context determines whether or not a given hostname should be trusted. It is up to you to decide.
    //In this example, if the hostname is "some_malicious_host" we refect it, otherwise we accept the hostname
    private HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {

            @Override
            public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
                if(hostname.equals("some_malicious_hostname")){
                    return false;
                }else{
                  return true;
                }
            }
        };
    }


    //This is how to setup an SSL context. In this example, we are accepting all ssl certificates.
    //You would implement your own logic to decide wether or not to trust a cert.
    private SSLContext getSSLContext() {
        javax.net.ssl.TrustManager x509 = new javax.net.ssl.X509TrustManager() {

            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException {
                return;
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException {
                return;
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        SSLContext ctx = null;
        try {
            ctx = SSLContext.getInstance("SSL");
            ctx.init(null, new javax.net.ssl.TrustManager[]{x509}, null);
        } catch (java.security.GeneralSecurityException ex) {
        }
        return ctx;
    }

    public static void main(String args[]){
        OnsetRestWebserviceExample client = new OnsetRestWebserviceExample();
        client.getLatestDataFile();
        System.out.println("success");
    }

}