/*
 * Copyright (c) 2007-2009 by The Broad Institute, Inc. and the Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * This software is licensed under the terms of the GNU Lesser General Public License (LGPL), Version 2.1 which
 * is available at http://www.opensource.org/licenses/lgpl-2.1.php.
 *
 * THE SOFTWARE IS PROVIDED "AS IS." THE BROAD AND MIT MAKE NO REPRESENTATIONS OR WARRANTIES OF
 * ANY KIND CONCERNING THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT
 * OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE.  IN NO EVENT SHALL THE BROAD OR MIT, OR THEIR
 * RESPECTIVE TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, AND AFFILIATES BE LIABLE FOR ANY DAMAGES OF
 * ANY KIND, INCLUDING, WITHOUT LIMITATION, INCIDENTAL OR CONSEQUENTIAL DAMAGES, ECONOMIC
 * DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER THE BROAD OR MIT SHALL
 * BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE
 * FOREGOING.
 */

package org.broad.tribble.util;

import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.*;

/**
 * Created by IntelliJ IDEA.
 * User: jrobinso
 * Date: Sep 23, 2009
 * Time: 5:51:21 PM
 * To change this template use File | Settings | File Templates.
 */
public class HttpUtils {

    private static Logger log = Logger.getLogger(HttpUtils.class);

    /**
     * Proxy settings (can be null)
     * TODO -- making this a global static is very ugly, and should be fixed, but doing so will require some IGV refactoring
     */
    private static ProxySettings proxySettings = null;

    public static String getHeaderField(URL url, String name) {

        URLConnection conn = null;
        try {
            // Create a URLConnection object for a URL
            conn = openConnection(url);
            conn.setReadTimeout(5000);
            return conn.getHeaderField(name);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        finally {
            if (conn != null && conn instanceof HttpURLConnection) {
                ((HttpURLConnection) conn).disconnect();
            }
        }
    }

    public static long getContentLength(URL url) {

        String contentLengthString = HttpUtils.getHeaderField(url, "Content-length");
        if (contentLengthString == null) {
            return -1;
        } else {
            try {
                return Long.parseLong(contentLengthString);
            }
            catch (NumberFormatException e) {
                log.error("Error parsing content length string: " + contentLengthString);
                return -1;
            }
        }
    }

    public static boolean resourceAvailable(URL url) {
        URLConnection conn = null;
        try {
            // Create a URLConnection object for a URL
            conn = openConnection(url);
            conn.setReadTimeout(5000);
            if (conn.getHeaderField("ETag") != null) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        finally {
            if (conn != null && conn instanceof HttpURLConnection) {
                ((HttpURLConnection) conn).disconnect();
            }
        }
    }


    /**
     * Wraps url.openConnection(),  and adds proxy authentication if required.
     *
     * @param url
     * @return
     * @throws java.io.IOException
     */
    public static HttpURLConnection openConnection(URL url) throws IOException {

        if (proxySettings != null && proxySettings.useProxy && proxySettings.proxyHost != null && proxySettings.proxyPort > 0) {
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxySettings.proxyHost, proxySettings.proxyPort));
            HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
            if (proxySettings.auth && proxySettings.user != null && proxySettings.pw != null) {
                String encodedUserPwd = base64Encode(proxySettings.user + ":" + proxySettings.pw);
                conn.setRequestProperty("Proxy-Authorization", "Basic " + encodedUserPwd);
            }
            return conn;

        } else {
            return (HttpURLConnection) url.openConnection();
        }
    }


    // TODO -- replace use of sun package
    public static String base64Encode(String str) {
        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        byte[] bytes = str.getBytes();
        return encoder.encode(bytes);

    }

    // TODO -- replace use of sun package
    public static String base64Decode(String str) {
        try {
            return new String((new sun.misc.BASE64Decoder()).decodeBuffer(str));
        } catch (IOException e) {
            log.error("Error decoding string: " + str, e);
            return str;
        }
    }


    public static void setProxySettings(ProxySettings ps) {
        proxySettings = ps;
    }


    public static class ProxySettings {
        boolean auth = false;
        String user;
        String pw;
        boolean useProxy;
        String proxyHost;
        int proxyPort = -1;

        public ProxySettings(boolean useProxy, String user, String pw, boolean auth, String proxyHost, int proxyPort) {
            this.auth = auth;
            this.proxyHost = proxyHost;
            this.proxyPort = proxyPort;
            this.pw = pw;
            this.useProxy = useProxy;
            this.user = user;
        }
    }
}
