/*
 * File:     OurURL.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;


/**
 * under java 1.4 there are problems dealing with UNC file paths the
 * \\host\myfile -> host=myhost path = /myfile while it should be host="" and
 * path = //host/myfile otherwise it doesnot work OurURL is a wrapper around
 * URL that handles these problems it also adrresses the problem that a
 * filepath that starts with a driveletter e.g. C: is not seen as an absolute
 * path, OurURL puts an '/' before it this way the context sensitive
 * constructor(s): URL(URL context, String path) work good! Addition: also
 * need to transform \ -> / for that!!
 * !!class is not serializable!!(todo)
 */
public class OurURL {
    private URL url;
    private String urlToString;

    /**
     * Creates a new OurURL instance
     *
     * @param url DOCUMENT ME!
     */
    public OurURL(URL url) throws MalformedURLException {
        try {
            this.url = new URL(url.getProtocol(), url.getHost(), url.getPort(),
                    absDevLet(url.getFile()).replace('\\', '/'));
        } catch (MalformedURLException e) {
            //System.out.println("OurURL: MalformedURLException - " + url);
            throw e;
        }

        // no need to throw something since URL was well formed
    }

    /**
     * Creates a new OurURL instance
     *
     * @param spec DOCUMENT ME!
     *
     * @throws MalformedURLException DOCUMENT ME!
     */
    public OurURL(String spec) throws MalformedURLException {
        spec = spec.replace('\\', '/');

        if (spec.startsWith("file:")) {
            url = new URL("file", "", -1, absDevLet(spec.substring(5)));
        } else {
            try {
                url = new URL(encode(spec));
            } catch (MalformedURLException mue) {
                // just for logging!
                //System.err.println("OurURL: constr: MalformedURLException for: "+spec);
                throw mue;
            }
        }
    }

    /**
     * Creates a new OurURL instance
     *
     * @param protocol DOCUMENT ME!
     * @param host DOCUMENT ME!
     * @param port DOCUMENT ME!
     * @param file DOCUMENT ME!
     *
     * @throws MalformedURLException DOCUMENT ME!
     */
    public OurURL(String protocol, String host, int port, String file)
        throws MalformedURLException {
        file = file.replace('\\', '/');

        try {
            file = absDevLet(file);

            if (protocol.equals("http")) {
                file = encode(file);
            }

            url = new URL(protocol, host, port, file);
        } catch (MalformedURLException mue) {
            // just for logging!
            //System.err.println("OurURL: constr: MalformedURLException for: "+protocol+", "+host+", "+port+", "+file);
            throw mue;
        }
    }

    /**
     * Creates a new OurURL instance
     *
     * @param protocol DOCUMENT ME!
     * @param host DOCUMENT ME!
     * @param port DOCUMENT ME!
     * @param file DOCUMENT ME!
     * @param handler DOCUMENT ME!
     *
     * @throws MalformedURLException DOCUMENT ME!
     */
    public OurURL(String protocol, String host, int port, String file,
        URLStreamHandler handler) throws MalformedURLException {
        file = file.replace('\\', '/');

        try {
            file = absDevLet(file);

            if (protocol.equals("http")) {
                file = encode(file);
            }

            url = new URL(protocol, host, port, file, handler);
        } catch (MalformedURLException mue) {
            // just for logging!
            //System.err.println("OurURL: constr: MalformedURLException for: "+protocol+", "+host+", "+port+", "+file);
            throw mue;
        }
    }

    /**
     * Creates a new OurURL instance
     *
     * @param protocol DOCUMENT ME!
     * @param host DOCUMENT ME!
     * @param file DOCUMENT ME!
     *
     * @throws MalformedURLException DOCUMENT ME!
     */
    public OurURL(String protocol, String host, String file)
        throws MalformedURLException {
        file = file.replace('\\', '/');
        file = absDevLet(file);

        if (protocol.equals("http")) {
            file = encode(file);
        }

        try {
            url = new URL(protocol, host, file);
        } catch (MalformedURLException mue) {
            // just for logging!
            //System.err.println("OurURL: constr: MalformedURLException for: "+protocol+", "+host+", "+file);
            throw mue;
        }
    }

    /**
     * Creates a new OurURL instance
     *
     * @param context DOCUMENT ME!
     * @param spec DOCUMENT ME!
     *
     * @throws MalformedURLException DOCUMENT ME!
     */
    public OurURL(URL context, String spec) throws MalformedURLException {
        if (context != null) {
            spec = encode(spec.replace('\\', '/'));

            try {
                url = new URL(context, absDevLet(spec));
            } catch (MalformedURLException mue) {
                // just for logging!
                //System.err.println("OurURL: constr: MalformedURLException for: "+context+", "+spec);
                throw mue;
            }
        } else {
            url = (new OurURL(spec)).toURL();
        }
    }

    /**
     * Creates a new OurURL instance
     *
     * @param context DOCUMENT ME!
     * @param spec DOCUMENT ME!
     *
     * @throws MalformedURLException DOCUMENT ME!
     */
    public OurURL(OurURL context, String spec) throws MalformedURLException {
        if (context != null) {
            spec = encode(spec.replace('\\', '/'));

            //System.out.println("OurURL constr: "+context+", "+spec);
            url = new URL(context.toURL(), absDevLet(spec));

            //System.out.println("OurURL constr: "+context+", "+absDevLet(spec)+", "+url);
        } else {
            url = (new OurURL(spec)).toURL();
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public URL toURL() {
        return url;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getProtocol() {
        return url.getProtocol();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public int getPort() {
        return url.getPort();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getPath() {
        String path = url.getPath();

        if ((path.length() > 1) && (path.charAt(0) == '/') &&
                (path.charAt(2) == ':')) { // absolutised device name

            return path.substring(1);
        } else {
            return path;
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getHost() {
        return url.getHost();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getFile() {
        String path = url.getPath();

        if ((path.length() > 1) && (path.charAt(0) == '/') &&
                (path.charAt(2) == ':')) { // absolutised device name

            return path.substring(1);
        } else {
            return path;
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param url DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public boolean sameFile(OurURL url) {
        return this.url.sameFile(url.toURL());
    }

    /**
     * DOCUMENT ME!
     *
     * @param obj DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public boolean equals(Object obj) {
        return url.equals(((OurURL) obj).toURL());
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public Object getContent() throws IOException {
        return url.getContent();
    }

    /**
     * DOCUMENT ME!
     *
     * @param classes DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public Object getContent(Class[] classes) throws IOException {
        return url.getContent(classes);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getAuthority() {
        return url.getAuthority();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public URLConnection openConnection() throws IOException {
        return url.openConnection();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public InputStream openStream() throws IOException {
        return url.openStream();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String toString() {
        return decode(url.toString());
    }

    /**
    * returns an encoded url string suitable for use in HTTP resource access
    */
    public String toEncodedString() {
        return url.toString();
    }

    /**
    * returns an decoded url string suitable for display
    */
    public String toDecodedString() {
        return toString();
    }

    static private String absDevLet(String s) {
        if ((s != null) && (s.length() > 2) && (s.charAt(1) == ':')) {
            s = "/" + s;
        }

        if (s.startsWith("file:") && (s.length() > 6) && (s.charAt(6) == ':')) {
            s = "file:/" + s.substring(5);
        }

        return s;
    }

    static private String encode(String s) {
        /*if( s.indexOf(" ")>=0){
            try {
                throw new Exception("space test");
            }catch(Exception e){ e.printStackTrace(); }
        }
         */
        String r = null;
        r = s.replaceAll(" ", "%20");

        return r;
    }

    static private String decode(String s) {
        String r = null;
        r = s.replaceAll("%20", " ");

        /*if( s.indexOf("%20")>=0){
            try {
                throw new Exception("decode space test->"+r);
            }catch(Exception e){ e.printStackTrace(); }
        }*/
        return r;
    }

    //////////////////////////////////////////////////////////////////////////
}
