package org.klomp.snarkxl.web;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;

import org.i2p.i2psnarkxl.template.web.HtmlGenerator;
import org.i2p.i2psnarkxl.peermanager.utils.BTPeerIDByteDecoder;
import org.klomp.snarkxl.I2PSnarkUtil;
import org.klomp.snarkxl.MetaInfo;
import org.klomp.snarkxl.Peer;
import org.klomp.snarkxl.Snark;
import org.klomp.snarkxl.SnarkManager;
import org.klomp.snarkxl.Storage;
import org.klomp.snarkxl.TrackerClient;

import org.i2p.i2psnarkxl.Client; // XL
import org.i2p.i2psnarkxl.server.ClientProcess;
/**
 *
 */
public class I2PSnarkXLServlet extends HttpServlet {
    private I2PAppContext _context;
    private Log _log;
    private SnarkManager _manager;
    private HtmlGenerator _htmlGenerator;
    private static long _nonce;
    private boolean xlServletInit = false;
    private boolean xlServletUseTemplates = false;
    private String nickname = "UNSET";
    private String xlServletConfigFile = null;
    public static final String PROP_CONFIG_FILE = "dummyxl.configFile";
    String servletName = null;
    
    public void init(ServletConfig cfg) throws ServletException {
        super.init(cfg);
        _context = I2PAppContext.getGlobalContext();
        _log = _context.logManager().getLog(I2PSnarkXLServlet.class);
        _nonce = _context.random().nextLong();
        _manager = SnarkManager.instance();
        _htmlGenerator = HtmlGenerator.instance();
        _htmlGenerator.setManager(_manager);
        
        String configFile = _context.getProperty(PROP_CONFIG_FILE);
        if ( (configFile == null) || (configFile.trim().length() <= 0) )
            configFile = "dummyxl.config";//hopefully nobody name a clone 'dummyxl' ;toDo: find a betterway to intentify the clients name
        
        // workaround to findout the usernamed servlet at startup
        ServletContext sc = cfg.getServletContext();
        servletName = sc.getServletContextName();
        if(servletName != null){
            if(servletName.startsWith("/")){
                servletName = servletName.substring(1);
                xlServletConfigFile = servletName + ".config";
                this.nickname = servletName;
                _manager.setNickname(nickname);
                _manager.loadConfig(xlServletConfigFile);
                xlServletInit = true;
                _manager.setXLServletInit(xlServletInit);
                //setHEADER_BEGIN();
                _manager.addMessage("cfg name: " + sc.getServletContextName());
            }else{
                _manager.loadConfig(configFile);
            }
        }else{
            _manager.loadConfig(configFile);
        }
    }
    
    private synchronized void startClientProcess(HttpServletRequest req, HttpServletResponse resp){
        // Loop indefinitely while waiting for clients to connect
        if ( true ) {
            int timeBeforeTimeout = -1; 
            
            if ( req.getParameter("image") != null ) {
                timeBeforeTimeout = 300;// *  Thread.sleep(10 ) = 3 seconds
            }else if ( req.getParameter("themes") != null ) {
                timeBeforeTimeout = 15000;// *  Thread.sleep(10 ) = 150 seconds // a fresh started torrent with a new tunnel could take a while
            // accept() does not return until a client requests a connection
            //Socket clientSocket = serverSocket.accept();
            }
            // Now that a client has arrived, create an instance of our special
            // thread subclass to respond to it.
            try{
                ClientProcess clientServer = new ClientProcess( req, resp,servletName,_nonce );
                clientServer.start();
                int weakup = 0;
                while(!clientServer.isReady()){
                    weakup++;
                    try{
                        Thread.sleep(10 );
                    }catch (InterruptedException e2) {
                        e2.printStackTrace();
                    }
                    if(timeBeforeTimeout > 0 && weakup > timeBeforeTimeout){// max 150 second// -1 == ignores the classic page but could stay forever!
                        _log.error("clientServer needs to long! break request: " + req );
                        if (clientServer != null){
                            clientServer.stopped = true; // isReady again
                            clientServer.interrupt();
                        }
                        try{
                            if ( req.getParameter("image") != null )// do not fire for a simple image
                                fireDisplayTimeout("see: log",req, resp);
                        }catch(IOException ioe){
                            //
                        }
                        break;
                    }
                }
                //clientServer = null;
            }catch(ServletException se){
                _log.error(" se: " + se);
            }
            
            //log.writeLog("");
            //log.writeLog("New client connected: " + clientServer.client.getRemoteSocketAddress()+" "+clientServer.client.getInetAddress());
            //if(!clientServer.client.isClosed()){
            //    clientServer.client.setSoTimeout(10000);
            //}
        }
    }
    
    private void fireDisplayTimeout(String reason, HttpServletRequest req, HttpServletResponse resp) throws IOException{
        // 404
        String ERROR_404 = "<html>\n" +
                "<head>\n" +
                "<title>" + "Timeout" + "</title>\n" +
                "</head>\n" +
                "<body>Timeout: " + reason  + "\n" +
                "</body>\n" +
                "</html>\n";
        try{
            PrintWriter out = resp.getWriter();
            out.write(ERROR_404);
        }catch(java.lang.IllegalStateException ise){
            _log.warn(" ise: " + ise);
        }
        return;
    }
    public synchronized void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");
        long stats[] = {0,0,0,0};
        
        //String image = req.getParameter("image");
        //if(req.getParameter("image") != null){
        //synchronized(Client.instance().clientsXL) {
        // HtmlGenerator hg = new HtmlGenerator(true);
        // hg.setManager(_manager);
        startClientProcess(req, resp);
        //return;
        //_htmlGenerator.fireImage("", req, resp);
        // hg = null;
        //}
        //}
    }
    
}
