/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package fr.gouv.finances.dgfip.xemelios.services;

import fr.gouv.finances.cp.xemelios.data.impl.MySqlDataLayer;
import fr.gouv.finances.dgfip.utils.Pair;
import fr.gouv.finances.dgfip.xemelios.auth.AuthEngine;
import fr.gouv.finances.dgfip.xemelios.auth.UnauthorizedException;
import fr.gouv.finances.dgfip.xemelios.auth.XemeliosUser;
import fr.gouv.finances.dgfip.xemelios.common.Constants;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentModel;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentsModel;
import fr.gouv.finances.dgfip.xemelios.common.config.ElementModel;
import fr.gouv.finances.dgfip.xemelios.common.config.EtatModel;
import fr.gouv.finances.dgfip.xemelios.common.config.Loader;
import fr.gouv.finances.dgfip.xemelios.data.DataAccessException;
import fr.gouv.finances.dgfip.xemelios.data.DataConfigurationException;
import fr.gouv.finances.dgfip.xemelios.data.DataImpl;
import fr.gouv.finances.dgfip.xemelios.data.DataLayerManager;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.ServletContextEvent;
import org.apache.log4j.Logger;

/**
 * @author CBO
 */
public class XemeliosHelper {

    private static final Logger logger = Logger.getLogger(XemeliosHelper.class);
    static private DocumentsModel documentsModel;
//    static private Menu rootMenu;
    static private AuthEngine authEngine;

    static public void init(ServletContextEvent event) {
        logger.debug(event.getServletContext().getServletContextName());
        System.setProperty(MySqlDataLayer.PROP_CONFIG_FILE_NAME, event.getServletContext().getRealPath("/WEB-INF/mysql.properties"));
        try {
            String documentDefsDirsName = event.getServletContext().getInitParameter("documents-def.dir");
            if (documentDefsDirsName == null) {
                documentDefsDirsName = event.getServletContext().getRealPath("WEB-INF/documents-def");
            } else {
                String baseDir = event.getServletContext().getRealPath("/");
logger.debug("baseDir is "+baseDir);
                File f = new File(baseDir).getParentFile().getParentFile().getParentFile().getParentFile();
                if(event.getServletContext().getInitParameter("baseDir")!=null) {
                    baseDir = event.getServletContext().getInitParameter("baseDir");
                    f = new File(baseDir);
                }
                documentDefsDirsName = documentDefsDirsName.replace("%basedir%", f.getCanonicalPath());
            }
            XemeliosHelper.documentsModel = Loader.getDocumentsInfos(documentDefsDirsName);
        } catch (Exception e) {
            throw new RuntimeException("Erreur lors du chargement des documents depuis " + System.getProperty(Constants.SYS_PROP_DOC_DEF_DIR), e);
        }
        try {
            MySqlDataLayer mySqlDataLayer = new MySqlDataLayer();
            setupDocumentsDirs(mySqlDataLayer); // il faut le faire avant le DataLayerManager.setDataImpl...
            DataLayerManager.regiterDataImpl(mySqlDataLayer.getClass().getName(), mySqlDataLayer.getClass());
            DataLayerManager.setDataImpl(MySqlDataLayer.class.getName());
        } catch (DataConfigurationException dce) {
            throw new RuntimeException("Erreur lors de la configuration de la couche d'accès aux données", dce);
        }
        AuthEngine.Holder.init("web.authEngineClassName");
//        AuthEngine.Holder.init("authEngineClassName");
//        XemeliosHelper.rootMenu = loadMenu();
    }

    public static Menu getMenu(XemeliosUser user) {
        return loadMenu(user);
    }

    public static void shutdown() {
        try {
            DataLayerManager.getImplementation().shutdown();
        } catch (DataConfigurationException dce) {
            throw new RuntimeException(dce);
        }
    }

    static public DocumentsModel getDocumentsModel() {
        return XemeliosHelper.documentsModel;
    }

    @Deprecated
    static public Menu getMenu() {
        //return XemeliosHelper.rootMenu;
        return null;
    }

    static public DocumentModel getDocumentsModel(String documentId) {
        for (DocumentModel dm : documentsModel.getDocuments()) {
            if (documentId.equals(dm.getId())) {
                return dm;
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    static public List<Pair> getCollectivites(XemeliosUser user, DocumentModel documentModel) throws DataConfigurationException, DataAccessException {
        try {
            // TODO: mettre la hierarchie des collectivites
            return new ArrayList(DataLayerManager.getImplementation().getCollectivites(documentModel, null, user));
        } catch (UnauthorizedException ex) {
            // ici, peut être ignorée
            return new ArrayList<Pair>();
        }
    }

    static public Pair getCollectivite(XemeliosUser user, DocumentModel documentModel, String collectiviteId) throws DataConfigurationException, DataAccessException {
        for (Pair pair : getCollectivites(user, documentModel)) {
            if (collectiviteId.equals(pair.key)) {
                return pair;
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    static public List<Pair> getBudgets(XemeliosUser user, DocumentModel documentModel, String collectiviteId) throws DataConfigurationException, DataAccessException, UnauthorizedException {
        return new ArrayList(DataLayerManager.getImplementation().getBudgets(documentModel, getCollectivite(user, documentModel, collectiviteId), user));
    }

    static public Pair getBudget(XemeliosUser user, DocumentModel documentModel, String collectiviteId, String budgetId) throws DataConfigurationException, DataAccessException, UnauthorizedException {
        for (Pair pair : getBudgets(user, documentModel, collectiviteId)) {
            if (budgetId.equals(pair.key)) {
                return pair;
            }
        }
        return null;
    }

    public static AuthEngine getAuthEngine() {
        return authEngine;
    }

    static private Menu loadMenu(XemeliosUser user) {
        Menu toReturn = new Menu(null, null, null, false);
        Menu accueilMenu = new Menu("accueil", null, "Accueil", false);
        if (user.hasRole(XemeliosUser.ROLE_IMPORT)) {
            accueilMenu.addChild(new Menu("imports", "displayImport.do", "Imports...", true));
        }
        if (user.hasRole(XemeliosUser.ROLE_EXPORT)) {
            accueilMenu.addChild(new Menu("simpleExports", "javascript:simpleExport()", "Exporter", false));
        }
        accueilMenu.addChild(new Menu("deconnect", "deconnexion.do", "Déconnexion", false));
        toReturn.addChild(accueilMenu);

        Menu searchMenu = new Menu("search", null, "Recherche", false);
        toReturn.addChild(searchMenu);
        for (DocumentModel dm : documentsModel.getDocuments()) {
            if (user.hasDocument(dm.getId())) {
                Enumeration<EtatModel> enumer2 = dm.getEtats().elements();
                Menu searchEntry = new Menu(dm.getId(), null, dm.getTitre(), false);
                int searchCount = 0;
                while (enumer2.hasMoreElements()) {
                    EtatModel em = enumer2.nextElement();
                    if (em.getDisplayInMenuIf() != null && !"true".equals(System.getProperty(em.getDisplayInMenuIf()))) {
                        continue;
                    }
                    Menu tmpMnu = null;
                    if (!dm.isGroupMenuItem()) {
                        tmpMnu = new Menu(em.getId(), null, em.getTitre(), false);
                    } else {
                        tmpMnu = searchEntry;
                    }
                    for (ElementModel elm : em.getSearchableElements()) {
                        if (!elm.isDisplay()) {
                            continue;
                        }
                        tmpMnu.addChild(new Menu(elm.getId(), "search.do?documentId=" + dm.getId() + "&etatId=" + em.getId() + "&elementId=" + elm.getId(), elm.getTitre(), true));
                        searchCount++;
                    }
                    if (tmpMnu != searchEntry) {
                        if (tmpMnu.getChilds().size() > 0) {
                            searchEntry.addChild(tmpMnu);
                        }
                    }
                }
                if (searchCount > 0) {
                    searchMenu.addChild(searchEntry);
                }
            }
        }

        if (user.hasRole(XemeliosUser.ROLE_SEARCH)) {
            Menu navigateMenu = new Menu("navigate", null, "Navigation", false);
            for (DocumentModel dm : documentsModel.getDocuments()) {
                if (user.hasDocument(dm.getId())) {
                    if (dm.isBrowsable()) {
                        navigateMenu.addChild(new Menu("nav-" + dm.getId(), "javascript:openNavigation(\\'" + dm.getId() + "\\')", dm.getTitre(), false));
                    }
                }
            }
            if (navigateMenu.getChilds().size() > 0) {
                toReturn.addChild(navigateMenu);
            }
        }

        if(user.hasRole(XemeliosUser.ROLE_EXPORT)) {
            Menu exportMenu = new Menu("exports", null, "Exports", false);
            exportMenu.addChild(new Menu("exportConfig","javascript:configExport()","Configurer",false));
            exportMenu.addChild(new Menu("exportRun","javascript:complexExport()","Ex&eacute;cuter",false));
            exportMenu.addChild(new Menu("exportJobs", "displayExportJobs.do", "Mes exports...", true));
            toReturn.addChild(exportMenu);
        }
        Menu helpMenu = new Menu("help","./user-guide/index.html","?",true);
        toReturn.addChild(helpMenu);
        return toReturn;
    }

    static private void setupDocumentsDirs(DataImpl dataImpl) throws DataConfigurationException {
        // Can be set by jvm arg like this java -Dxemelios.documents.def.dir=C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/carte-achat/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/cfg-paye/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/facture-depense/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/facture-recette/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/pes-aller/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/pes-facture/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/quittancement/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/rapport/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/versement/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/edmn/conf,C:/CBO/cvs/gaea.local.axyus.com/XEMELIOS/src/erar/conf ...
//        System.out.println("System.getProperty(Constants.SYS_PROP_DOC_DEF_DIR) : " + System.getProperty(Constants.SYS_PROP_DOC_DEF_DIR));
        //if (System.getProperty(Constants.SYS_PROP_DOC_DEF_DIR) == null) {
        String documentsParentDirAsString = dataImpl.getParameterValue("documentsParentDir");
        if (documentsParentDirAsString != null) {
            File documentsParentDir = new File(documentsParentDirAsString);
            if (documentsParentDir != null && documentsParentDir.isDirectory()) {
                StringBuilder sb = new StringBuilder();
                File childs[] = documentsParentDir.listFiles();
                for (File child : childs) {
                    if (child.isDirectory()) {
                        if (sb.length() > 0) {
                            sb.append(",");
                        }
                        sb.append(child.getAbsolutePath());
                    }
                }
                if (sb.length() > 0) {
                    System.setProperty(Constants.SYS_PROP_DOC_DEF_DIR, sb.toString());
                }
            }
        }
    //}
    }

    private XemeliosHelper() {
    }
}
