package fr.iri.thd.sonyengine.web;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.ws.rs.core.Application;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;

import com.sleepycat.persist.EntityCursor;

import fr.iri.thd.sonyengine.core.DataAccessor;
import fr.iri.thd.sonyengine.core.DbEnv;
import fr.iri.thd.sonyengine.core.EngineAccessor;
import fr.iri.thd.sonyengine.core.MovieFragment;
import fr.iri.thd.sonyengine.core.Tag;

public class ServletContainer extends
		com.sun.jersey.spi.container.servlet.ServletContainer {

	public static final String INIT_DATABASE_PATH = "initDatabasePath";
	public static final String UNTRAINED_LIMIT = "untrainedLimit";

	/**
	 * 
	 */
	private static final long serialVersionUID = -447765110849619632L;

	public static final String DB_ENV_ATTRIBUTE = "DB_ENV";
	public static final String DB_PATH_ATTRIBUTE = "DB_PATH";
	public static final String UNTRAINED_LIMIT_ATTRIBUTE = "UNTRAINED_LIMIT";
	
	
	public ServletContainer() {
	}

	public ServletContainer(Class<? extends Application> appClass) {
		super(appClass);
	}

	public ServletContainer(Application app) {
		super(app);
	}


	public void init() throws ServletException {
		
		String log4jLocation = this.getInitParameter("log4j-properties-location");
		ServletContext sc = this.getServletContext();

		if (log4jLocation == null) {
			System.err.println("*** No log4j-properties-location init param, so initializing log4j with BasicConfigurator");
			BasicConfigurator.configure();
		}
		else {
			
			final Properties prop = new Properties();
			final InputStream propStream = sc.getResourceAsStream(log4jLocation); 
			if (propStream != null) {
				try {
					prop.load(propStream);
				} catch (IOException e) {
					System.err.println("*** " + log4jLocation + " file not found, so initializing log4j with BasicConfigurator");
					BasicConfigurator.configure();
				}
				finally {
					try {
						propStream.close();
					}
					catch (IOException e) {
						// do nothing
					}
				}
				System.out.println("Initializing log4j with: " + log4jLocation);
				PropertyConfigurator.configure(prop);
			}
			else {
				System.err.println("*** " + log4jLocation + " file not found, so initializing log4j with BasicConfigurator");
				BasicConfigurator.configure();
			}
		}
		
		super.init();
		
		String databasePath = this.getServletContext().getInitParameter(INIT_DATABASE_PATH);
		
		if(databasePath == null || databasePath.length() == 0)
			throw new ServletException("Database path not found (null or empty)");

		File databasePathFile = new File(databasePath);
		
                try {
		    if(!databasePathFile.exists())
		    {
			databasePathFile.mkdirs();
		    }
                }
                catch(Exception e) {
                    throw new ServletException("Unable to create database path " + databasePath, e);
                }
		DbEnv env = new DbEnv();
		env.setup(databasePathFile, false, true);
		
		// set DbEnv in servlet context
		sc.setAttribute(ServletContainer.DB_ENV_ATTRIBUTE, env);
		sc.setAttribute(ServletContainer.DB_PATH_ATTRIBUTE, databasePath);
		
		final String untrainedLimitStr = this.getServletContext().getInitParameter(UNTRAINED_LIMIT);
		
		int untrainedLimit = 0;
		
		if(untrainedLimitStr != null)
		    untrainedLimit = Integer.parseInt(untrainedLimitStr);
		
		sc.setAttribute(ServletContainer.UNTRAINED_LIMIT_ATTRIBUTE, new Integer(untrainedLimit));
		
        EngineAccessor.getInstance().setUntrainedLimit(untrainedLimit);
		EngineAccessor.getInstance().setDbEnv(env);
		
		//load all entities
		DataAccessor da = new DataAccessor(env.getEntityStore());
		
		EntityCursor<MovieFragment> movieFragmentItems = da.movieFragmentById.entities();
		
		try {
			for(MovieFragment item : movieFragmentItems) {
			    EngineAccessor.getInstance().createMovieFragment(item.getId());
			}
		}
		finally {
			movieFragmentItems.close();
		}
		
		EntityCursor<Tag> tagItems = da.tagById.entities();
		
		try {
			for(Tag item : tagItems) {
			    EngineAccessor.getInstance().addTag(item.getName(), item.getSegment());
			}
		}
		finally {
			tagItems.close();
		}
		
		EngineAccessor.getInstance().train();
	}
	
	public void destroy() {
		DbEnv env = (DbEnv)this.getServletContext().getAttribute(DB_ENV_ATTRIBUTE);
		
		if(env != null) {
			env.close();
		}
	}
	
}
