package eu.dnetlib.efg1914.various.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import eu.dnetlib.efg1914.various.locales.MyLocale;
import eu.dnetlib.efg1914.various.utils.SetLocalesVariables;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import eu.dnetlib.efg1914.authoring.components.dao.ArchiveDAO;
import eu.dnetlib.efg1914.authoring.components.dao.ConfigurationDAO;
import eu.dnetlib.efg1914.various.managers.PageCreator;
import eu.dnetlib.efg1914.various.managers.components.CreditsPage;

@SuppressWarnings("serial")
public class CreditsPageServlet extends HttpServlet {

    private ApplicationContext context = null;
    private ArchiveDAO archiveDao = null;
    private ConfigurationDAO configurationDao = null;
    private String sourcePath = null;

    private String configurationName = null;
    private Transformer transformer = null;

    //The String containing the name of the file that contains the code for statistics
    private String trackingFileName = null;
    private String trackingFileContent = null;
    private InputStream is = null;
    private String locale = null;
    private String locale2 = null;

    private String showLanguages = null;


    private static Logger logger = Logger.getLogger(CreditsPageServlet.class);


    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        setArchiveDao((ArchiveDAO) context.getBean("archiveDao"));
        setConfigurationDao((ConfigurationDAO) context.getBean("configurationDao"));
        setSourcePath((String) context.getBean("gridfsPath"));
        setConfigurationName((String) context.getBean("configurationName"));
        setTrackingFileName((String) context.getBean("trackingFileName"));
        setLocale((String) context.getBean("locale"));
        setLocale2((String) context.getBean("locale2"));

        is = this.getClass().getClassLoader().getResourceAsStream(trackingFileName);

        try {
            if (is != null) {
                trackingFileContent = IOUtils.toString(is);
                is.close();
            } else {
                trackingFileContent = "";
            }

        } catch (IOException e) {
            logger.warn("Could not load tracking file.", e);

        }
        setShowLanguages((String) context.getBean("showLanguages"));
        if (!(showLanguages.equals("true") || showLanguages.equals("false"))) {
            showLanguages = "false";
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        PrintWriter writer = null;

        VelocityEngine ve = new VelocityEngine();
        ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        VelocityContext context = null;
        String lan = (String) request.getSession().getAttribute("language");
        if (lan == null || lan.isEmpty()) {
            request.getSession().setAttribute("language", locale);
            lan = (String) request.getSession().getAttribute("language");
        }
        try {
            CreditsPage creditsPage = PageCreator.createCreditsPage(configurationDao, archiveDao, configurationName);

            Template t = ve.getTemplate("/eu/dnetlib/efg1914/various/servlet/menu.vm");
            StringWriter menuWriter = new StringWriter();
            context = new VelocityContext();
            context.put("current", "2");
            context.put("sourcePath", sourcePath);

            SetLocalesVariables.setContextVariables(context, lan, locale, locale2, showLanguages);
            t.merge(context, menuWriter);

            transformer = TransformerFactory.newInstance().newTemplates(new StreamSource(this.getClass().getClassLoader().getResourceAsStream("/eu/dnetlib/efg1914/various/servlet/credits.xsl"))).newTransformer();
            transformer.setParameter("sourcePath", sourcePath);
            try {
                MyLocale myLocale = new MyLocale(lan);
                transformer.setParameter("pageTitle", myLocale.getValue("credits.pageTitle"));
                transformer.setParameter("tooltip", myLocale.getValue("credits.tooltip"));

            } catch (IOException e) {
                e.printStackTrace();
            }
            //add menu in transformer
            transformer.setParameter("menu", menuWriter.toString());

            //load screen warning page
            StringWriter warningWriter = new StringWriter();
            IOUtils.copy(this.getClass().getClassLoader().getResourceAsStream("/eu/dnetlib/efg1914/various/servlet/screenSizeWarning.html"), warningWriter);

            //add screen warning in transformer
            transformer.setParameter("screenSizeWarning", warningWriter.toString());
            transformer.setParameter("requestPath", request.getRequestURL().substring(0, request.getRequestURL().length() - request.getServletPath().length()));
            transformer.setParameter("requestUrl", request.getRequestURL());
            transformer.setParameter("trackingCode", trackingFileContent);

            JAXBContext jaxbcontext = JAXBContext.newInstance(CreditsPage.class);
            Marshaller marshaller = jaxbcontext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

            StringWriter stringWriter = new StringWriter();
            marshaller.marshal(creditsPage, stringWriter);

            response.setCharacterEncoding("UTF-8");
            writer = response.getWriter();
            transformer.transform(new StreamSource(new StringReader(stringWriter.toString())), new StreamResult(writer));
            logger.debug("main page xml" + stringWriter.toString());

        } catch (Exception e) {
            logger.error("Fail to load main page", e);
        }
    }

    public String getLocale2() {
        return locale2;
    }

    public void setLocale2(String locale2) {
        this.locale2 = locale2;
    }

    public String getShowLanguages() {
        return showLanguages;
    }

    public void setShowLanguages(String showLanguages) {
        this.showLanguages = showLanguages;
    }

    public void setLocale(String locale) {
        this.locale = locale;
    }

    public ApplicationContext getContext() {
        return context;
    }

    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    public String getSourcePath() {
        return sourcePath;
    }

    public void setSourcePath(String sourcePath) {
        this.sourcePath = sourcePath;
    }

    public ConfigurationDAO getConfigurationDao() {
        return configurationDao;
    }

    public void setConfigurationDao(ConfigurationDAO configurationDao) {
        this.configurationDao = configurationDao;
    }

    public String getConfigurationName() {
        return configurationName;
    }

    public void setConfigurationName(String configurationName) {
        this.configurationName = configurationName;
    }

    public ArchiveDAO getArchiveDao() {
        return archiveDao;
    }

    public void setArchiveDao(ArchiveDAO archiveDao) {
        this.archiveDao = archiveDao;
    }

    public String getTrackingFileName() {
        return trackingFileName;
    }

    public void setTrackingFileName(String trackingFileName) {
        this.trackingFileName = trackingFileName;
    }
}
