/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and Others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Takashi ITOH - initial API and implementation
 *******************************************************************************/

package org.eclipse.actf.model.internal.flash.proxy;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.actf.model.flash.bridge.IWaXcoding;
import org.eclipse.actf.model.flash.bridge.WaXcodingFactory;
import org.eclipse.actf.model.flash.proxy.internal.INTERNET_PER_CONN_OPTION;
import org.eclipse.actf.model.flash.proxy.internal.INTERNET_PER_CONN_OPTION_LIST;
import org.eclipse.actf.model.flash.proxy.internal.WSTR;
import org.eclipse.actf.model.flash.proxy.internal.WinInet;
import org.eclipse.actf.model.internal.flash.proxy.logs.ProxyLogHandler;
import org.eclipse.actf.util.win32.MemoryUtil;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;

import com.ibm.icu.text.MessageFormat;




public class ProxyManager {

	public static boolean initLogger = false;
	public static boolean forceProxy = false;
	private static String noProxy = "";  //$NON-NLS-1$
    
	static {
		String[] temp = Platform.getApplicationArgs();
		for( int i=0; i<temp.length; i++ ) {
			if( "-initLogger".equals(temp[i]) ) { //$NON-NLS-1$
				initLogger = true;
			}
			else if( "-forceProxy".equals(temp[i]) ) { //$NON-NLS-1$
				forceProxy = true;
			}
			else if( "-noProxy".equals(temp[i]) ) { //$NON-NLS-1$
				if( i < temp.length-1 ) {
					String nextArg = temp[i+1];
					if( nextArg.startsWith("|") && nextArg.endsWith("|") ) { //$NON-NLS-1$ //$NON-NLS-2$
						noProxy = nextArg;
					}
				}
			}
		}
        if( Platform.inDebugMode() ) {
            System.out.println("initLogger = "+initLogger); //$NON-NLS-1$
            System.out.println("forceProxy = "+forceProxy); //$NON-NLS-1$
            System.out.println("noProxy = "+noProxy); //$NON-NLS-1$
        }
	}

    private INTERNET_PER_CONN_OPTION_LIST savedList;
    private int savedAddress;
    private int hSession;
    private boolean needRestore = false;
    private int currentPort = 0;
    private static String PROTCOL_HTTP =   "http"; //$NON-NLS-1$
    private static String PROTCOL_HTTPS =  "https"; //$NON-NLS-1$
    private static String PROTCOL_FTP =    "ftp"; //$NON-NLS-1$
    private static String PROTCOL_GOPHER = "gopher"; //$NON-NLS-1$
//    private static String[] PROTCOL_EXTRA = new String[]{"https","ftp","gopher"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    
    public ProxyManager() {
        // Save default settings
        savedList = new INTERNET_PER_CONN_OPTION_LIST(4);
        savedList.perConnOptions[0].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_FLAGS;
        savedList.perConnOptions[1].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_SERVER;
        savedList.perConnOptions[2].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_BYPASS;
        savedList.perConnOptions[3].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_AUTOCONFIG_URL;
        savedAddress = MemoryUtil.GlobalAlloc(INTERNET_PER_CONN_OPTION_LIST.sizeof);
        savedList.getData(savedAddress);
        int[] pInt = new int[]{INTERNET_PER_CONN_OPTION_LIST.sizeof};
        WinInet.InternetQueryOptionW(0,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION,savedAddress,pInt);
        savedList.setData(savedAddress);
        WSTR wsAgent = new WSTR("Agent"); //$NON-NLS-1$
        hSession = WinInet.InternetOpenW(wsAgent.getAddress(),WinInet.INTERNET_OPEN_TYPE_DIRECT,0,0,0);
        wsAgent.dispose();
    }
    
    public void startProxy(int port, int swfVersion, int timeout,
                           boolean swfBootloader, boolean swfTranscoder) {
        IWaXcoding waXcoding = getIWaXcoding();
        waXcoding.setPort(port);
        waXcoding.setSWFTranscodingMinimumVersion(swfVersion);
        waXcoding.setTimeout(timeout);
        waXcoding.setExternalProxyFlag(false);
        waXcoding.setSWFBootloaderFlag(swfBootloader);
        waXcoding.setSWFTranscodingFlag(swfTranscoder);
        String extProxy = getDefaultProxy(PROTCOL_HTTP);
        if( null != extProxy ) {
            int pos = extProxy.indexOf(':');
            if( -1 != pos ) {
                try {
                    String extHost = extProxy.substring(0,pos);
                    String portStr = extProxy.substring(pos+1);
                    int extPort = Integer.parseInt(portStr);
                    waXcoding.setExternalProxyFlag(true);
                    waXcoding.setExternalProxy(extHost,extPort);
                    if( Platform.inDebugMode() ) {
                        System.out.println("Using external proxy "+extHost+":"+extPort); //$NON-NLS-1$ //$NON-NLS-2$
                    }
                } catch( Exception e ) {
                }
            }
        }
        ProxyLogHandler.configure();      // Configure our log handler
        waXcoding.start(initLogger);           // Start WaXcoding without log handler
        if( !initLogger ) {
        	ProxyLogHandler.resetLogLevel();
        }
        currentPort = waXcoding.getPort();
    }
    
    public void stopProxy() {
        if( 0 != currentPort ) {
            getIWaXcoding().stop();
            currentPort = 0;
        }
    }
    
    public void setInternetOptions(boolean isGlobal) {
        if( 0 != savedAddress ) {
            if( 0 == currentPort ) {
                invokeSetOption(hSession,savedAddress);
                invokeSetOption(0,savedAddress);
                needRestore = false;
            }
            else {
//                INTERNET_PER_CONN_OPTION_LIST list = new INTERNET_PER_CONN_OPTION_LIST(3);
//                list.perConnOptions[0].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_FLAGS;
//                list.perConnOptions[0].dwValue=INTERNET_PER_CONN_OPTION.PROXY_TYPE_PROXY | INTERNET_PER_CONN_OPTION.PROXY_TYPE_DIRECT;
//                list.perConnOptions[1].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_SERVER;
//                list.perConnOptions[1].strValue.setString(getProxyString());
//                list.perConnOptions[2].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_BYPASS;
//                list.perConnOptions[2].strValue.setString(null);
                INTERNET_PER_CONN_OPTION_LIST list = new INTERNET_PER_CONN_OPTION_LIST(2);
                list.perConnOptions[0].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_FLAGS;
                list.perConnOptions[0].dwValue=INTERNET_PER_CONN_OPTION.PROXY_TYPE_AUTO_PROXY_URL | INTERNET_PER_CONN_OPTION.PROXY_TYPE_DIRECT;
                list.perConnOptions[1].dwOption=INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_AUTOCONFIG_URL;
                list.perConnOptions[1].strValue.setString(getAutoConfigURL(isGlobal||forceProxy));
                int address = MemoryUtil.GlobalAlloc(INTERNET_PER_CONN_OPTION_LIST.sizeof);
                list.getData(address);
                invokeSetOption(hSession, address);
                invokeSetOption(0, isGlobal ? address : savedAddress);
                needRestore = isGlobal;
                MemoryUtil.GlobalFree(address);
                list.dispose();
            }
        }
    }
    
    public void dispose() {
        ProxyLogHandler.removeHandler();
        stopProxy();
        if( 0 != hSession ) {
            WinInet.InternetCloseHandle(hSession);
        }
        if( 0 != savedAddress ) {
            if( needRestore ) {
                WinInet.InternetSetOptionW(0,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION,savedAddress,INTERNET_PER_CONN_OPTION_LIST.sizeof);
            }
            MemoryUtil.GlobalFree(savedAddress);
            savedList.dispose();
        }
    }

    private void invokeSetOption(int handle, int address) {
        WinInet.InternetSetOptionW(handle,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION,address,INTERNET_PER_CONN_OPTION_LIST.sizeof);
        WinInet.InternetSetOptionW(handle,WinInet.INTERNET_OPTION_SETTINGS_CHANGED,0,0);
        WinInet.InternetSetOptionW(handle,WinInet.INTERNET_OPTION_REFRESH,0,0);
    }
    
//    private String getProxyString() {
//        String result = PROTCOL_HTTP+"=localhost:"+currentPort; //$NON-NLS-1$
//        for( int i=0; i<PROTCOL_EXTRA.length; i++ ) {
//            String s = getDefaultProxy(PROTCOL_EXTRA[i]);
//            if( null!=s && s.length()>0 ) {
//                result += ";"+PROTCOL_EXTRA[i]+"="+s; //$NON-NLS-1$ //$NON-NLS-2$
//            }
//        }
//        return result;
//    }
    
    private String getDefaultProxy(String protocol) {
        if( 0 != (savedList.perConnOptions[0].dwValue & INTERNET_PER_CONN_OPTION.PROXY_TYPE_PROXY) ) {
            String defaultProxy = savedList.perConnOptions[1].strValue.getString();
            if( null != defaultProxy ) {
                if( -1 == defaultProxy.indexOf('=') ) {
                    return defaultProxy;
                }
                Matcher m = Pattern.compile(protocol+"=(.+)").matcher(defaultProxy); //$NON-NLS-1$
                if( m.find() ) {
                    String s = m.group(1);
                    if( null != s ) {
                        int sep = s.indexOf(';');
                        return -1==sep ? s : s.substring(0,sep);
                    }
                }
            }
        }
        return null;
    }
    
    private IWaXcoding getIWaXcoding() {
        return WaXcodingFactory.getWaXcoding();
    }
    
    private String getAutoConfigURL(boolean disableAutoProxy) {
		String pac = readPluginFile("templates/proxy.pac"); //$NON-NLS-1$
        if( null != pac ) {
        	String httpProxy = getProxyString("localhost:"+currentPort); //$NON-NLS-1$
        	pac = pac.replaceAll("\\$NOPROXY_EXTS\\$",  disableAutoProxy ? "" : noProxy) //$NON-NLS-1$ //$NON-NLS-2$
		        	 .replaceAll("\\$HTTP_PROXY\\$",    httpProxy) //$NON-NLS-1$
		        	 .replaceAll("\\$HTTP_DIRECT\\$",   getProxyString(getDefaultProxy(PROTCOL_HTTP))) //$NON-NLS-1$
		        	 .replaceAll("\\$HTTPS_DIRECT\\$",  getProxyString(getDefaultProxy(PROTCOL_HTTPS))) //$NON-NLS-1$
		        	 .replaceAll("\\$FTP_DIRECT\\$",    getProxyString(getDefaultProxy(PROTCOL_FTP))) //$NON-NLS-1$
		        	 .replaceAll("\\$GOPHER_DIRECT\\$", getProxyString(getDefaultProxy(PROTCOL_GOPHER))); //$NON-NLS-1$
//            System.out.println(pac);
        	OutputStream os = null;
        	try {
                IPath pacPath = ProxyPlugin.getDefault().getStateLocation().append("proxy.pac"); //$NON-NLS-1$
                os = new FileOutputStream(pacPath.toFile());
    			OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8"); //$NON-NLS-1$
    			writer.write(pac);
    			writer.close();
                return "file://"+pacPath.toString(); //$NON-NLS-1$
        	}
        	catch( Exception e ) {
        		e.printStackTrace();
        	}
        	finally {
        		if( null != os ) {
    				try {
    					os.close();
    				} 
    				catch (IOException e) {
    				}
        		}
        	}
        }
    	return null;
    }
    
    private static String getProxyString(String defaultProxy) {
    	return null != defaultProxy ? MessageFormat.format("PROXY {0}; DIRECT", new Object[]{defaultProxy}) : "DIRECT"; //$NON-NLS-1$ //$NON-NLS-2$
    }
    
    private static String readPluginFile(String path) {
    	InputStream is = null;
    	try {
        	URL url = FileLocator.resolve(ProxyPlugin.getDefault().getBundle().getEntry(path));
			is = url.openStream();
			Reader reader = new InputStreamReader(is);
			StringBuffer sb = new StringBuffer();
			char[] buff = new char[4096];
			int result;
			while( -1 != (result=reader.read(buff)) ) {
				sb.append(buff, 0, result);
			}
			return sb.toString();
    	}
    	catch( Exception e ) {
    		e.printStackTrace();
    	}
    	finally {
    		if( null != is ) {
				try {
					is.close();
				} 
				catch (IOException e) {
				}
    		}
    	}
    	return null;
    }
}
