package com.n2bb.web.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import javax.servlet.http.HttpServletRequest;

import com.n2bb.util.N2bbSettings;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Utility methods for webapp.
 *
 * @author kmatsuoka
 */
public class WebUtil {    
    private static final Log log = LogFactory.getLog(N2bbSettings.N2BB_LOG);

    /**
     * Gets integer ID request parameter.
     *
     * @param request   servlet request
     * @return          id, or null if no/invalid id parameter
     */
    public static Integer getID(HttpServletRequest request) {
        return getInteger(request, "id");
    }

    /**
     * Gets integer value for request parameter.
     *
     * @param request   servlet request
     * @param parameter parameter name
     * @return          integer value for parameter, or null if no/invalid parameter
     */
    public static Integer getInteger(HttpServletRequest request, String parameter) {
        Integer intValue = null;
        String value = request.getParameter(parameter);

        try {
            if (value != null) {
                intValue = new Integer(value);
            }
        }
        catch (NumberFormatException ex) {
            log.error("unparseable " + parameter + ": " + value);
        }

        return intValue;
    }

    /**
     * Gets long value for request parameter.
     *
     * @param request   servlet request
     * @param parameter parameter name
     * @return          long value for parameter, or null if no/invalid parameter
     */
    public static Long getLong(HttpServletRequest request, String parameter) {
        Long longValue = null;
        String value = request.getParameter(parameter);

        try {
            if (value != null) {
                longValue = new Long(value);
            }
        }
        catch (NumberFormatException ex) {
            log.error("unparseable " + parameter + ": " + value);
        }

        return longValue;
    }

    /**
     * Gets an array of integers from an array of strings.
     *
     * @param strings   array of integers represented as strings
     * @return          array of integers
     */
    public static int[] getIntegerArray(String[] strings) {
        int[] ints = new int[strings.length];
        for (int i = 0; i < strings.length; i++) {
            ints[i] = new Integer(strings[i]).intValue();
        }
        return ints;
    }

    /**
     * Gets an array of longs from an array of strings.
     *
     * @param strings   array of longs represented as strings
     * @return          array of longs
     */
    public static long[] getLongArray(String[] strings) {
        long[] longs = new long[strings.length];
        for (int i = 0; i < strings.length; i++) {
            longs[i] = new Long(strings[i]).longValue();
        }
        return longs;
    }

    /**
     * Gets an array of shorts from an array of strings,
     * compacted to skip any empty/null strings in the source array.
     *
     * @param strings   array of shorts represented as strings
     * @return          array of shorts
     * @throws  NumberFormatException if any of the strings are invalid shorts, but not for empty/null strings.
     */
    public static short[] getSignedShortArray(String[] strings) throws NumberFormatException {
        List shortList = new ArrayList();
        for (int i = 0; i < strings.length; i++) {
            String s = strings[i];
            if (s != null && !s.trim().equals("")) {
                shortList.add(getSignedShort(s.trim()));
            }
        }
        short[] shorts = new short[shortList.size()];
        int i = 0;
        for (Iterator iterator = shortList.iterator(); iterator.hasNext();) {
            shorts[i++] = ((Short) iterator.next()).shortValue();

        }
        return shorts;
    }

    /**
     * Gets an array of strings from an array of shorts.
     * If short array is null, return a zero-length string array.
     *
     * @param shorts    array of shorts
     * @return          array of strings
     */
    public static String[] getStringArray(short[] shorts) {
        if (shorts == null) {
            return new String[0];
        }

        String[] strings = new String[shorts.length];
        for (int i = 0; i < shorts.length; i++) {
            strings[i] = "" + shorts[i];
        }
        return strings;
    }

    /**
     * Gets an array of strings from an array of objects.
     * If object array is null, return a zero-length string array.
     *
     * @param objects    array of objects
     * @return          array of strings
     */
    public static String[] getStringArray(Object[] objects) {
        if (objects == null) {
            return new String[0];
        }

        String[] strings = new String[objects.length];
        for (int i = 0; i < objects.length; i++) {
            strings[i] = "" + objects[i];
        }
        return strings;
    }

    /**
     * Gets an array of strings representing unsigned shorts from an array of shortsr.
     * If object array is null, return a zero-length string array.
     *
     * @param shorts    array of shorts
     * @return          array of strings
     */
    public static String[] getUnsignedShortStringArray(Short[] shorts) {
        if (shorts == null) {
            return new String[0];
        }

        String[] strings = new String[shorts.length];
        for (int i = 0; i < shorts.length; i++) {
            strings[i] = "" + getUnsignedShort(shorts[i].shortValue());
        }
        return strings;
    }

    public static String[] getStringArray(Collection collection) {
        return getStringArray(collection.toArray(new Object[0]));
    }

    public static short[] getShortArray(Short[] shortObjects) {
        short[] shorts = new short[shortObjects.length];
        for (int i = 0; i < shortObjects.length; i++) {
            Short shortObject = shortObjects[i];
            shorts[i] = (shortObject == null ? 0 : shortObject.shortValue());
        }
        return shorts;
    }

    /**
     * Gets ID for exception.   Useful for tracking exceptions seen in browser
     * back to webapp log.
     *
     * @return  ID for exception
     */
    public static String getExceptionID() {
        String exceptionId;

        try {
            exceptionId = InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException ue) {
            exceptionId = "localhost";
        }

        return exceptionId + "/" + System.currentTimeMillis();
    }

    /**
     * Gets a string representation of an unsigned short (between 0 and 65535)
     * from a signed short (between -32768 and 32767).
     *
     * @param s signed short (between -32768 and 32767)
     * @return string representation of an unsigned short (between 0 and 65535)
     * @throws NumberFormatException
     */
    public static int getUnsignedShort(short s) {
        if (s >= 0) {
            return (int) s;
        }
        else {
            return 65536 + s;
        }
    }

    /**
     * Gets a signed short (between -32768 and 32767) from a string representation
     * of an unsigned short (between 0 and 65535).
     *
     * @param s string representation of an unsigned short (between 0 and 65535)
     * @return signed short (between -32768 and 32767)
     * @throws NumberFormatException
     */
    public static Short getSignedShort(String s) throws NumberFormatException {
        int i = Integer.parseInt(s);
        if (i < 0 || i > 65535) {
            throw new NumberFormatException(s);
        }
        else if (i < Short.MAX_VALUE) {
            return new Short((short) i);
        }
        else {
            return new Short((short) (i - 65536));
        }
    }
}
