/*******************************************************************************
 * Copyright (c) 2010 Angelo Zerr 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:
 *     Angelo Zerr <angelo.zerr@gmail.com> - Initial API and implementation 
 *******************************************************************************/
package org.eclipse.jst.server.jetty.core.internal.jetty7;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jst.server.core.internal.ProgressUtil;
import org.eclipse.jst.server.jetty.core.JettyPlugin;
import org.eclipse.jst.server.jetty.core.WebModule;
import org.eclipse.jst.server.jetty.core.internal.IJettyWebModule;
import org.eclipse.jst.server.jetty.core.internal.JettyConfiguration;
import org.eclipse.jst.server.jetty.core.internal.JettyConstants;
import org.eclipse.jst.server.jetty.core.internal.Messages;
import org.eclipse.jst.server.jetty.core.internal.Trace;
import org.eclipse.jst.server.jetty.core.internal.config.JettyXMLConfig;
import org.eclipse.jst.server.jetty.core.internal.config.PathFileConfig;
import org.eclipse.jst.server.jetty.core.internal.config.StartConfig;
import org.eclipse.jst.server.jetty.core.internal.config.StartIni;
import org.eclipse.jst.server.jetty.core.internal.config.WebdefaultXMLConfig;
import org.eclipse.jst.server.jetty.core.internal.util.IOUtils;
import org.eclipse.jst.server.jetty.core.internal.xml.Factory;
import org.eclipse.jst.server.jetty.core.internal.xml.jetty7.ServerInstance;
import org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server.Connector;
import org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server.Server;
import org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server.WebApp;
import org.eclipse.jst.server.jetty.core.internal.xml.jetty7.webapp.WebAppContext;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.ServerPort;

public class Jetty7Configuration extends JettyConfiguration implements JettyConstants
{
    private StartIni _startIniConfig;

    protected ServerInstance _serverInstance;
    
    private boolean _isServerDirty;
    
    // property change listeners
    private transient List<PropertyChangeListener> _propertyListeners;

    
    public Jetty7Configuration(IFolder path)
    {
        super(path);
    }
    
    public Collection<ServerPort> getServerPorts()
    {
        List<ServerPort> ports = new ArrayList<ServerPort>();

        // first add server port
        try {
        	int port = Integer.parseInt(_serverInstance.getAdminPort());
        	ports.add(new ServerPort("server", Messages.portServer, port, "TCPIP"));
        } catch (Exception e) {
        	// ignore
        }

        // add connectors
        try
        {

            Collection<Connector> connectors = _serverInstance.getConnectors();
            if (connectors != null)
            {
            	int portId = 0;
                for (Connector connector : connectors)
                {
                    int port = -1;
                    try
                    {
                        port = Integer.parseInt(connector.getPort());
                    }
                    catch (Exception e)
                    {
                        // ignore
                    }
                    
                    String id = Integer.toString(portId++);
                    String type = connector.getType();
                    String name = "HTTP";
                    String className = type.substring(type.lastIndexOf('.')+1); 
                    if ("SelectChannelConnector".equals(className) || 
                    		"SocketConnector".equals(className)) {
                    	name = "HTTP";
                    } else if ("SslSelectChannelConnector".equals(className) ||
                    		"SslSocketConnector".equals(className)) {
                    	name = "SSL";
                    } else if ("Ajp13SocketConnector".equals(className)) {
                    	name = "AJP";
                    }
                    	
                    ports.add(new ServerPort(id,name,port,name));
                    // TODO : how get HTTP type port???

                    // ports.add(new ServerPort(portId, name, port, protocol2,
                    // contentTypes, advanced));
                }
            }

        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error getting server ports",e);
        }

        return ports;

        // String instanceServiceName = serverInstance.getService().getName();
        // int size = server.getServiceCount();
        // for (int i = 0; i < size; i++) {
        // Service service = server.getService(i);
        // int size2 = service.getConnectorCount();
        // for (int j = 0; j < size2; j++) {
        // Connector connector = service.getConnector(j);
        // String name = "HTTP/1.1";
        // String protocol2 = "HTTP";
        // boolean advanced = true;
        // String[] contentTypes = null;
        // int port = -1;
        // try {
        // port = Integer.parseInt(connector.getPort());
        // } catch (Exception e) {
        // // ignore
        // }
        // String protocol = connector.getProtocol();
        // if (protocol != null && protocol.length() > 0) {
        // if (protocol.startsWith("HTTP")) {
        // name = protocol;
        // }
        // else if (protocol.startsWith("AJP")) {
        // name = protocol;
        // protocol2 = "AJP";
        // }
        // else {
        // // Get Jetty equivalent name if protocol handler class specified
        // name = (String)protocolHandlerMap.get(protocol);
        // if (name != null) {
        // // Prepare simple protocol string for ServerPort protocol
        // int index = name.indexOf('/');
        // if (index > 0)
        // protocol2 = name.substring(0, index);
        // else
        // protocol2 = name;
        // }
        // // Specified protocol is unknown, just use as is
        // else {
        // name = protocol;
        // protocol2 = protocol;
        // }
        // }
        // }
        // if (protocol2.toLowerCase().equals("http"))
        // contentTypes = new String[] { "web", "webservices" };
        // String secure = connector.getSecure();
        // if (secure != null && secure.length() > 0) {
        // name = "SSL";
        // protocol2 = "SSL";
        // } else
        // advanced = false;
        // String portId;
        // if (instanceServiceName != null &&
        // instanceServiceName.equals(service.getName()))
        // portId = Integer.toString(j);
        // else
        // portId = i +"/" + j;
        // ports.add(new ServerPort(portId, name, port, protocol2, contentTypes,
        // advanced));
        // }

    }
    
    /**
     * Return the port number.
     * 
     * @return int
     */
    public ServerPort getAdminPort()
    {
        Collection<ServerPort> serverPorts = getServerPorts();
        
        for (ServerPort serverPort : serverPorts)
        {
            // Return only an HTTP port from the selected Service
            if (serverPort.getId().equals("server"))
            {
                return serverPort;
            }
        }
        
        return null;
    }


    /**
     * Return a list of the web modules in this server.
     * 
     * @return java.util.List
     */
    public List<WebModule> getWebModules()
    {
        List<WebModule> list = new ArrayList<WebModule>();

        try
        {
            Collection<WebAppContext> contexts = _serverInstance.getContexts();
            if (contexts != null)
            {
                for (WebAppContext context : contexts)
                {
                    String documentBase = context.getDocumentBase();
                    String path = context.getContextPath();
                    String memento = context.getMemento();
                    WebModule module = new WebModule(path,documentBase,memento,true);
                    list.add(module);
                }
            }
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error getting project refs",e);
        }
        return list;
    }

    public void addWebModule(int i, IJettyWebModule module)
    {
        try
        {
            WebAppContext context = _serverInstance.createContext(module.getDocumentBase(),module.getMemento(),module.getPath());
            if (context != null)
            {
                // context.setDocBase(module.getDocumentBase());
                // context.setPath(module.getPath());
                // context.setReloadable(module.isReloadable() ? "true" :
                // "false");
                // if (module.getMemento() != null &&
                // module.getMemento().length() > 0)
                // context.setSource(module.getMemento());
                _isServerDirty = true;
                firePropertyChangeEvent(__ADD_WEB_MODULE_PROPERTY,null,module);
            }
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error adding web module " + module.getPath(),e);
        }

    }

    /**
     * Removes a web module.
     * 
     * @param index
     *            int
     */
    public void removeWebModule(int index)
    {
        try
        {
            _serverInstance.removeContext(index);
            _isServerDirty = true;
            firePropertyChangeEvent(__REMOVE_WEB_MODULE_PROPERTY,null,index);
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error removing module ref " + index,e);
        }
    }

    protected void firePropertyChangeEvent(String propertyName, Object oldValue, Object newValue)
    {
        if (_propertyListeners == null)
            return;

        PropertyChangeEvent event = new PropertyChangeEvent(this,propertyName,oldValue,newValue);
        try
        {
            Iterator<PropertyChangeListener> iterator = _propertyListeners.iterator();
            while (iterator.hasNext())
            {
                try
                {
                    PropertyChangeListener listener = iterator.next();
                    listener.propertyChange(event);
                }
                catch (Exception e)
                {
                    Trace.trace(Trace.SEVERE,"Error firing property change event",e);
                }
            }
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error in property event",e);
        }
    }

    /**
     * Adds a property change listener to this server.
     * 
     * @param listener
     *            java.beans.PropertyChangeListener
     */
    public void addPropertyChangeListener(PropertyChangeListener listener)
    {
        if (_propertyListeners == null)
            _propertyListeners = new ArrayList<PropertyChangeListener>();
        _propertyListeners.add(listener);
    }

    /**
     * Removes a property change listener from this server.
     * 
     * @param listener
     *            java.beans.PropertyChangeListener
     */
    public void removePropertyChangeListener(PropertyChangeListener listener)
    {
        if (_propertyListeners != null)
            _propertyListeners.remove(listener);
    }

    /**
     * @see JettyConfiguration#load(IPath, IProgressMonitor)
     */
    public void load(IPath path, IPath runtimeBaseDirectory, IProgressMonitor monitor) throws CoreException
    {
        try
        {
            monitor = ProgressUtil.getMonitorFor(monitor);
            monitor.beginTask(Messages.loadingTask,5);

            Factory serverFactory = null;

            // Load config.ini
            this._startIniConfig = new StartIni(path);

            // Load jetty.xml files
            List<PathFileConfig> jettyXMLConfiFiles = _startIniConfig.getJettyXMLFiles();
            List<Server> servers = new ArrayList<Server>();
            Server server = null;
            File file = null;
            IPath jettyPath = null;
            if (jettyXMLConfiFiles.size() > 0)
            {
                for (PathFileConfig jettyXMLConfig : jettyXMLConfiFiles)
                {
                    file = jettyXMLConfig.getFile();

                    jettyPath = jettyXMLConfig.getPath();
                    serverFactory = new Factory();
                    serverFactory.setPackageName("org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server");
                    server = (Server)serverFactory.loadDocument(JettyXMLConfig.getInputStream(file));
                    server.setFile(file);
                    server.setPath(jettyPath);
                    servers.add(server);
                }
            }

            WebApp webApp = null;
            PathFileConfig pathFileConfig = _startIniConfig.getWebdefaultXMLConfig();
            if (pathFileConfig != null)
            {
                File webAppFile = pathFileConfig.getFile();
                IPath webAppPath = pathFileConfig.getPath();

                Factory webdefaultFactory = new Factory();
                webdefaultFactory.setPackageName("org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server");
                webApp = (WebApp)webdefaultFactory.loadDocument(WebdefaultXMLConfig.getInputStream(webAppFile));
                webApp.setFile(webAppFile);
                webApp.setPath(webAppPath);
            }
            
            File adminPortFile = _startIniConfig.getAdminPortFile();
            String adminPort = null;
            if (adminPortFile != null && adminPortFile.exists()) 
            {
            	BufferedReader reader = new BufferedReader(new FileReader(adminPortFile));
            	adminPort = reader.readLine();
            	reader.close();
            }
            // check for catalina.policy to verify that this is a v4.0 config
            // InputStream in = new
            // FileInputStream(path.append("catalina.policy").toFile());
            // in.read();
            // in.close();
            monitor.worked(1);

            // server = (Server) serverFactory.loadDocument(new FileInputStream(
            // path.append("jetty.xml").toFile()));
            _serverInstance = new ServerInstance(servers,webApp,runtimeBaseDirectory);
            if (adminPort != null)
            {
            	_serverInstance.setAdminPort(adminPort);
            }
            // monitor.worked(1);
            //
            // webAppDocument = new
            // WebAppDocument(path.append("webdefault.xml"));
            // monitor.worked(1);

            // jettyUsersDocument = XMLUtil.getDocumentBuilder().parse(new
            // InputSource(new
            // FileInputStream(path.append("jetty-users.xml").toFile())));
            monitor.worked(1);

            // load policy file
            // policyFile = JettyVersionHelper.getFileContents(new
            // FileInputStream(path.append("catalina.policy").toFile()));
            //monitor.worked(1);

            if (monitor.isCanceled())
                return;
            monitor.done();
        }
        catch (Exception e)
        {
            Trace.trace(Trace.WARNING,"Could not load Jetty v7.x configuration from " + path.toOSString() + ": " + e.getMessage());
            throw new CoreException(new Status(IStatus.ERROR,JettyPlugin.PLUGIN_ID,0,NLS.bind(Messages.errorCouldNotLoadConfiguration,path.toOSString()),e));
        }
    }

    public void load(IFolder folder, IPath runtimeBaseDirectory, IProgressMonitor monitor) throws CoreException
    {
        try
        {
            monitor = ProgressUtil.getMonitorFor(monitor);
            monitor.beginTask(Messages.loadingTask,800);

            Factory serverFactory = null;

            // Load config.ini
            this._startIniConfig = new StartIni(folder);

            // Load jetty.xml files
            List<PathFileConfig> jettyXMLConfiFiles = _startIniConfig.getJettyXMLFiles();
            List<Server> servers = new ArrayList<Server>();
            Server server = null;
            File file = null;
            IPath jettyPath = null;
            if (jettyXMLConfiFiles.size() > 0)
            {
                for (PathFileConfig jettyXMLConfig : jettyXMLConfiFiles)
                {
                    file = jettyXMLConfig.getFile();
                    jettyPath = jettyXMLConfig.getPath();
                    serverFactory = new Factory();
                    serverFactory.setPackageName("org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server");
                    server = (Server)serverFactory.loadDocument(new FileInputStream(file));
                    server.setFile(file);
                    server.setPath(jettyPath);
                    servers.add(server);
                }
            }
            // check for catalina.policy to verify that this is a v4.0 config
            // InputStream in = new
            // FileInputStream(path.append("catalina.policy").toFile());
            // in.read();
            // in.close();
            monitor.worked(1);

            WebApp webApp = null;
            PathFileConfig pathFileConfig = _startIniConfig.getWebdefaultXMLConfig();
            if (pathFileConfig != null)
            {
                File webAppFile = pathFileConfig.getFile();
                IPath webAppPath = pathFileConfig.getPath();

                Factory webdefaultFactory = new Factory();
                webdefaultFactory.setPackageName("org.eclipse.jst.server.jetty.core.internal.xml.jetty7.server");
                webApp = (WebApp)webdefaultFactory.loadDocument(new FileInputStream(webAppFile));
                webApp.setFile(webAppFile);
                webApp.setPath(webAppPath);
            }
            File adminPortFile = _startIniConfig.getAdminPortFile();
            String adminPort = null;
            if (adminPortFile != null && adminPortFile.exists()) 
            {
            	BufferedReader reader = new BufferedReader(new FileReader(adminPortFile));
            	adminPort = reader.readLine();
            	reader.close();
            }
            // server = (Server) serverFactory.loadDocument(new FileInputStream(
            // path.append("jetty.xml").toFile()));
            _serverInstance = new ServerInstance(servers,webApp,runtimeBaseDirectory);
            if (adminPort != null) 
            {
            	_serverInstance.setAdminPort(adminPort);
            }
            // check for catalina.policy to verify that this is a v4.0 config
            // IFile file = folder.getFile("catalina.policy");
            // if (!file.exists())
            // throw new CoreException(new Status(IStatus.WARNING,
            // JettyPlugin.PLUGIN_ID, 0,
            // NLS.bind(Messages.errorCouldNotLoadConfiguration,
            // folder.getFullPath().toOSString()), null));

            // load server.xml
            // IFile file = folder.getFile("jetty.xml");
            // InputStream in = file.getContents();
            // serverFactory = new Factory();
            // serverFactory.setPackageName("org.eclipse.jst.server.jetty.core.internal.xml.server70");
            // server = (Server) serverFactory.loadDocument(in);
            // serverInstance = new ServerInstance(server);
            // monitor.worked(200);
            //
            // // load web.xml
            // file = folder.getFile("webdefault.xml");
            // webAppDocument = new WebAppDocument(file);
            // monitor.worked(200);

            // load jetty-users.xml
            // file = folder.getFile("jetty-users.xml");
            // in = file.getContents();

            // jettyUsersDocument = XMLUtil.getDocumentBuilder().parse(new
            // InputSource(in));
            //monitor.worked(200);

            // load catalina.policy
            // file = folder.getFile("catalina.policy");
            // in = file.getContents();
            // policyFile = JettyVersionHelper.getFileContents(in);
            monitor.worked(200);

            if (monitor.isCanceled())
                throw new Exception("Cancelled");
            monitor.done();
        }
        catch (Exception e)
        {
            Trace.trace(Trace.WARNING,"Could not reload Jetty v7.x configuration from: " + folder.getFullPath() + ": " + e.getMessage());
            throw new CoreException(new Status(IStatus.ERROR,JettyPlugin.PLUGIN_ID,0,NLS.bind(Messages.errorCouldNotLoadConfiguration,folder.getFullPath()
                    .toOSString()),e));
        }

    }

    /**
     * Save the information held by this object to the given directory.
     * 
     * @param folder
     *            a folder
     * @param monitor
     *            a progress monitor
     * @throws CoreException
     */
    public void save(IFolder folder, IProgressMonitor monitor) throws CoreException
    {
        try
        {
            monitor = ProgressUtil.getMonitorFor(monitor);
            monitor.beginTask(Messages.savingTask,1200);
            if (monitor.isCanceled())
                return;

            _startIniConfig.save(folder.getFile(__START_INI),monitor);
            _serverInstance.save(folder,monitor);

            // get etc/realm.properties
            // get etc/webdefault.xml

            InputStream in = null;
            IFolder newFolder = folder;
            IPath path = null;
            String filename = null;
            List<PathFileConfig> otherConfigs = _startIniConfig.getOtherConfigs();
            for (PathFileConfig pathFileConfig : otherConfigs)
            {
                path = pathFileConfig.getPath();
                if (path.segmentCount() > 1)
                {
                    newFolder = folder.getFolder(path.removeLastSegments(1));
                    IOUtils.createFolder(newFolder,monitor);
                }
                filename = pathFileConfig.getFile().getName();
                in = new FileInputStream(pathFileConfig.getFile());
                IFile file = newFolder.getFile(filename);
                if (file.exists())
                {
                    // if (isServerDirty)
                    file.setContents(in,true,true,ProgressUtil.getSubMonitorFor(monitor,200));
                    // else
                    // monitor.worked(200);
                }
                else
                    file.create(in,true,ProgressUtil.getSubMonitorFor(monitor,200));
            }

            // start.config from start.jar
            PathFileConfig startConfig = _startIniConfig.getStartConfig();
            if (startConfig != null)
            {
                File startJARFile = startConfig.getFile();
                InputStream stream = StartConfig.getInputStream(startJARFile);
                IFile file = folder.getFile("start.config");
                if (file.exists())
                {
                    // if (isServerDirty)
                    file.setContents(stream,true,true,ProgressUtil.getSubMonitorFor(monitor,200));
                    // else
                    // monitor.worked(200);
                }
                else
                    file.create(stream,true,ProgressUtil.getSubMonitorFor(monitor,200));

            }

            monitor.done();
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Could not save Jetty v7.x configuration to " + folder.toString(),e);
            throw new CoreException(new Status(IStatus.ERROR,JettyPlugin.PLUGIN_ID,0,NLS.bind(Messages.errorCouldNotSaveConfiguration,new String[]
            { e.getLocalizedMessage() }),e));
        }
    }

    public void importFromPath(IPath path, IPath runtimeBaseDirectory, boolean isTestEnv, IProgressMonitor monitor) throws CoreException
    {
        load(path,runtimeBaseDirectory,monitor);

        // for test environment, remove existing contexts since a separate
        // catalina.base will be used
        if (isTestEnv)
        {
            while (_serverInstance.removeContext(0))
            {
                // no-op
            }
        }
    }

    /**
     * Modify the port with the given id.
     * 
     * @param id
     *            java.lang.String
     * @param port
     *            int
     */
    public void modifyServerPort(String id, int port)
    {
        try
        {
            if ("server".equals(id))
            {
            	_serverInstance.setAdminPort(port+"");
                _isServerDirty = true;
                firePropertyChangeEvent(__MODIFY_PORT_PROPERTY,id, Integer.valueOf(port));
                return;
            }

			int connNum = Integer.parseInt(id);
			List<Connector> connectors = _serverInstance.getConnectors();
			Connector connector = connectors.get(connNum);
			connector.setPort(port + "");
			_isServerDirty = true;
			firePropertyChangeEvent(__MODIFY_PORT_PROPERTY, id, new Integer(port));            
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error modifying server port " + id,e);
        }
    }

    /**
     * Change a web module.
     * 
     * @param index
     *            int
     * @param docBase
     *            java.lang.String
     * @param path
     *            java.lang.String
     * @param reloadable
     *            boolean
     */
    public void modifyWebModule(int index, String docBase, String path, boolean reloadable)
    {
        try
        {
            WebAppContext context = _serverInstance.getContext(index);
            if (context != null)
            {
                context.setContextPath(path);
                context.save();
                _isServerDirty = true;
                WebModule module = new WebModule(path,docBase,null,reloadable);
                firePropertyChangeEvent(__MODIFY_WEB_MODULE_PROPERTY, Integer.valueOf(index),module);
            }
        }
        catch (Exception e)
        {
            Trace.trace(Trace.SEVERE,"Error modifying web module " + index,e);
        }
    }

}
