//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package de.ugoe.cs.autoquest.httpmonitor;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.Before;

import de.ugoe.cs.util.console.TextConsole;

/**
 *
 */
public abstract class AbstractTC {
    
    /**
     * 
     */
    protected static final TextConsole CONSOLE = new TextConsole(Level.FINEST);
    
    /**
     * 
     */
    protected final static String LOG_FILE_DIR = "target/tmp/logfiles/";
    
    /**
     * 
     */
    protected static final int PORT = 19098;
    
    /**
     * the jetty web server used for receiving messages
     */
    private Server dummyServer;
    
    /**
     * the servlet of the dummy web server responding to requests
     */
    private DummyServlet dummyServlet;

    /**
     * 
     */
    @Before
    public void setUp() throws Exception {
        // setup a simple HTTP server
        dummyServer = new Server(PORT + 1);
        
        ServletContextHandler root =
            new ServletContextHandler(dummyServer, "/", ServletContextHandler.SESSIONS);

        dummyServlet = new DummyServlet();
        root.addServlet(new ServletHolder(dummyServlet), "/*");
        
        dummyServer.start();
        
        setUpHook();
    }

    /**
     *
     */
    protected abstract void setUpHook() throws Exception;

    /**
     *
     */
    @After
    public void tearDown() throws Exception {
        // give all started servers a second to finalize their internal work after the test
        // execution. This prevents some unnecessary exceptions due to requests already processed
        // by the test case but not finalized on server side.
        Thread.sleep(1000);
        tearDownHook();

        if (dummyServer != null) {
            try {
                dummyServer.stop();
            }
            finally {
                dummyServer = null;
            }
        }
        
        deleteFiles(new File(LOG_FILE_DIR));
    }

    /**
     *
     */
    protected abstract void tearDownHook() throws Exception;

    /**
     *
     */
    protected String sendDummyMessage(String type, String message, String respMsg)
        throws Exception
    {
        dummyServlet.setResponse(respMsg);
        
        System.err.println("sending message: " + message);
        DefaultHttpClient httpclient = new DefaultHttpClient();
        HttpRequestBase httpRequest = null;
        
        if ("POST".equals(type)) {
            httpRequest = new HttpPost("http://localhost:" + PORT + "/");
            HttpEntity entity = new StringEntity(message, ContentType.TEXT_PLAIN);
            ((HttpPost) httpRequest).setEntity(entity);
        }
        else if ("GET".equals(type)) {
            httpRequest = new HttpGet("http://localhost:" + PORT + "/");
        }
        
        try {
            HttpResponse response = httpclient.execute(httpRequest);
            String responseStr = readStreamContentToString(response.getEntity().getContent());
            System.err.println("received response: " + message);
            return responseStr;
        }
        finally {
            httpRequest.releaseConnection();
        }
    }
    
    /**
     * 
     */
    protected String readStreamContentToString(InputStream stream) throws IOException {
        return readToString(new BufferedReader(new InputStreamReader(stream)));
    }
    
    /**
     * 
     */
    protected String readToString(BufferedReader reader) throws IOException {
        StringBuffer message = new StringBuffer();
        
        String line = reader.readLine();
        while (line != null) {
            System.err.println(line);
            if (message.length() > 0) {
                message.append('\n');
            }
            message.append(line);
            line = reader.readLine();
        }
        
        return message.toString();
    }

    /**
     *
     */
    protected void deleteFiles(File file) {
        if (file.exists()) {
            if (file.isDirectory()) {
                for (File child : file.listFiles()) {
                    deleteFiles(child);
                }
            }
            
            try {
                file.delete();
            }
            catch (Exception e) {
                // ignore and delete as much as possible
            }
        }
    }

}
