package jp.sourceforge.shovel.util;

import static jp.sourceforge.shovel.CommonConst.*;
import static jp.sourceforge.shovel.MobileCarrierType.*;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.seasar.framework.container.ComponentDef;
import org.seasar.framework.container.ContainerConstants;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

import jp.sourceforge.shovel.MobileCarrierType;
import jp.sourceforge.shovel.entity.IClient;
import jp.sourceforge.shovel.exception.ApplicationException;

public class HttpUtil {
    static final Pattern HTTP_PATTERN = Pattern.compile( "^http.*", Pattern.CASE_INSENSITIVE);
    public static boolean isAbsolutePath(String path) {
        Matcher matcher = HTTP_PATTERN.matcher(path);
        return matcher.matches();
    }
    public static void sendRedirect(HttpServletResponse response,  String path) throws IOException {
        //path = toAbsolutePath(path, null);
        //HttpServletResponse response = getResponse();
        //モバイルのjsessionid対策にencodeURLを通す
        response.sendRedirect(response.encodeURL(path));
    }
    public static String toAbsolutePath(String path, Map params) {
        HttpServletRequest request = getRequest();

        Matcher matcher = HTTP_PATTERN.matcher(path);
        if (!matcher.matches()) {
            try {
                String contextPath = request.getContextPath();
                path = contextPath + path;
                String referer = request.getHeader( HTTP_REFERER );
                if (referer != null) {
                    URL url = new URL( referer );
                    if (url.getPort() != -1) {
                        path = url.getProtocol() + "://" + url.getHost() + ":" + url.getPort() + path;
                    } else {
                        path = url.getProtocol() + "://" + url.getHost() + path;
                    }
                } else {
                    if (request.getServerPort() != 80) {
                        path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
                    } else {
                        path = request.getScheme() + "://" + request.getServerName() + path;
                    }
                }
            } catch (Exception e) {
                
            }
        }
        return toRequestFullPath(path, params, null);
    }

    public static String toRequestFullPath(String path, Map params) {
        return toRequestFullPath(path, params, null);
    }
    public static String toRequestFullPath( String path, Map params, Set ignore ) {
        String orginal = path;

        if( params == null ) return orginal;

        Iterator<?> it = params.keySet().iterator();
        if( it.hasNext() ) {
            orginal += "?";
        }
        while( it.hasNext() ) {
            String p = (String)it.next();
            if ( ignore != null && ignore.contains(p)) {
                continue;
            }

            try {
                String[] values = (String[])params.get( p );
                if( values == null ) continue;

                for ( int i = 0; i < values.length; i++ ) {
                    String value = URLEncoder.encode(values[i], "UTF8");
                    p = ( p + "=" + value );
                    if (i < values.length - 1) {
                        p += "&";
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (it.hasNext()) {
                p += "&";
            }
            orginal += p;
        }
        return orginal;
    }
    
    public static String toRequestFullPathExt(String path, Map params) {
        String orginal = path;

        if (params == null) {
            return orginal;
        }

        if (params != null) {
            Iterator<?> it = params.keySet().iterator();
            if (it.hasNext()) {
                orginal += "?";
            }
            while (it.hasNext()) {
                String p = (String)it.next();
                try {
                    Object[] values = (Object[])params.get(p);
                    if (values == null) {
                        continue;
                    }
    
                    for (int i = 0; i < values.length; i++) {
                        String value = URLEncoder.encode( String.valueOf(values[i]), "UTF8" );
                        p = ( p + "=" + value );
                        if (i < values.length - 1) {
                            p += "&";
                        }
                    }
                } catch ( Exception e ) {
                    e.printStackTrace();
                }
                if (it.hasNext()) {
                    p += "&";
                }
                orginal += p;
            }
        }
        return orginal;
    }
    
    public static IClient detectClient(String userAgent) throws ApplicationException {
        try {
            S2Container container = SingletonS2ContainerFactory.getContainer();
            ComponentDef[] defs = container.findComponentDefs(IClient.class);
            Class<?> parameterTypes[] = {String.class};
            Object parameters[] = {userAgent};
            for (ComponentDef def : defs) {
                Class<?> klass = def.getComponentClass();
                Method method = klass.getMethod("testUserAgent", parameterTypes);
                IClient client = (IClient)method.invoke(null, parameters);
                if (client != null) {
                    String os = "unknown";
                    if (userAgent.indexOf("windows") != -1) {
                        os = "windows";
                    } else if (userAgent.indexOf("mac") != -1) {
                        os = "mac";
                    }
                    client.setOs(os);
                    return client;
                }
            }
            return (IClient)container.getComponent("firefox");
        } catch (Exception ex) {
            //TODO エラー
            throw new ApplicationException("");
        }
    }
    
    public static Map parseParametersEasy(HttpServletRequest request) {
        if (!ServletFileUpload.isMultipartContent(request)) {
            return request.getParameterMap();
        }
        try {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(request.getContentLength() << 1);
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setSizeMax(request.getContentLength());
            upload.setHeaderEncoding(request.getCharacterEncoding());
            List<?> itemList = upload.parseRequest(request);
            Map<String, String> parameterMap = new HashMap<String, String>();
            for (Object item : itemList) {
                FileItem parameter = (FileItem)item;
                parameterMap.put( parameter.getFieldName(), parameter.getString() );
            }
            return parameterMap;
        } catch (FileUploadException e) {
            return null;
        }
    }
    public static String getRFC1123Time(Date time) {
        SimpleDateFormat rfc1123DateFormat = 
                new SimpleDateFormat("E, dd MMM yyyy hh:mm:ss zzz", java.util.Locale.US);
        rfc1123DateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
 
        return rfc1123DateFormat.format(time);
    }
    public static MobileCarrierType getMobileCarrierType(boolean ignoreHost) {
        String userAgent = getRequest().getHeader("User-Agent");
        String host = getRequest().getHeader("Remote-Host");
        if (userAgent.indexOf("DoCoMo") == 0) {
            if (ignoreHost || host.matches(".+\\.docomo\\.ne\\.jp$")) {
                return DOCOMO;
            }
        } else if (userAgent.indexOf("SoftBank") == 0 || userAgent.indexOf("Semulator") == 0 ||
                userAgent.indexOf("Vodafone") == 0 || userAgent.indexOf("Vemulator") == 0 ||
                userAgent.indexOf("MOT-") == 0 || userAgent.indexOf("MOTEMULATOR") == 0 ||
                userAgent.indexOf("J-PHONE") == 0 || userAgent.indexOf("J_EMULATOR") == 0) {
            if (ignoreHost || host.matches(".+\\.jp-.\\.ne\\.jp$")) {
                return SOFTBANK;
            }
        } else if (userAgent.indexOf("UP.Browser") == 0 || userAgent.indexOf("KDDI") == 0) {
            if (ignoreHost || host.matches(".+\\.ezweb\\.ne\\.jp$")) {
                return AU;
            }
        } else if (userAgent.matches("^Mozilla/3\\.0\\((?:DDIPOCKET|WILLCOM);") || userAgent.indexOf("PDXGW") == 0) {
            if (ignoreHost || host.matches(".+\\.prin\\.ne\\.jp$")) {
                return WILLCOM;
            }
        }
        return UNKNOWN;
    }
    static HttpServletRequest getRequest() {
        S2Container container = SingletonS2ContainerFactory.getContainer();
        return (HttpServletRequest)container.getComponent( ContainerConstants.REQUEST_NAME );

    }
}
