/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.extensions.scripting.core.api;

import org.apache.myfaces.extensions.scripting.core.common.util.FileUtils;
import org.apache.myfaces.extensions.scripting.core.engine.FactoryEngines;
import org.apache.myfaces.extensions.scripting.core.engine.api.ScriptingEngine;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.FilenameFilter;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;

import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.ENGINETYPE_JSF_JRUBY;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.ENGINE_TYPE_JSF_GROOVY;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.ENGINE_TYPE_JSF_JAVA;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.GROOVY_FILE_ENDING;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.JRUBY_FILE_ENDING;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.INIT_PARAM_INITIAL_COMPILE;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.INIT_PARAM_RESOURCE_PATH;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.INIT_PARAM_SCRIPTING_ADDITIONAL_CLASSPATH;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.INIT_PARAM_SCRIPTING_PACKAGE_WHITELIST;
import static org.apache.myfaces.extensions.scripting.core.api.ScriptingConst.JAVA_FILE_ENDING;

/**
 * @author Werner Punz (latest modification by $Author$)
 * @version $Revision$ $Date$
 */

public class Configuration
{
    private static final String WEB_INF_CLASSES = "/WEB-INF/classes";
    List<String> _additionalClassPath = new CopyOnWriteArrayList<String>();
    /**  kk
     * the package whitelist used by our system
     * to determine which packages are under control.
     * <p/>
     * Note an empty whitelist means, all packages with sourcedirs attached to.
     */
    Set<String> _packageWhiteList = new ConcurrentSkipListSet<String>();
    /**
     * we keep track of separate resource dirs
     * for systems which can use resource loaders
     * <p/>
     * so that we can load various resources as well
     * from separate source directories instead
     */
    volatile List<String> _resourceDirs = new CopyOnWriteArrayList<String>();

    String _initialCompile;

    WeakReference<ServletContext> _contextWeakReference = null;

    /**
     * the target compile path
     */
    volatile File _compileTarget = FileUtils.getTempDir();

    /**
     * the source dirs per scripting engine
     */
    volatile Map<Integer, CopyOnWriteArrayList<String>> _sourceDirs = new ConcurrentHashMap<Integer, CopyOnWriteArrayList<String>>();

    public Configuration(ServletContext context)
    {
        init(context);
    }

    public Configuration()
    {
    }


    private Collection<String> performWildCardSearch(String classPathEntry) {

        if(classPathEntry.toLowerCase().endsWith("*.jar")|| classPathEntry.toLowerCase().endsWith("*.zip")){
            //peform a full search of jars on the dir
            classPathEntry = classPathEntry.substring(0, classPathEntry.length()-5);
            File classPathDir = new File(classPathEntry);
            String[] foundFiles = classPathDir.list(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.toLowerCase().endsWith(".jar") || name.toLowerCase().endsWith(".zip");
                }
            });
            if(foundFiles == null) {
                return Collections.emptyList();
            }
            ArrayList<String> retVal = new ArrayList<String>(foundFiles.length);
            for(String foundFile: foundFiles) {
                retVal.add(classPathEntry+foundFile);
            }
            return retVal;
        }
        return Arrays.asList(new String[] {classPathEntry});
    }

    public void init(ServletContext context)
    {
        String packageWhiteList = context.getInitParameter(INIT_PARAM_SCRIPTING_PACKAGE_WHITELIST);
        packageWhiteList = (packageWhiteList == null) ? "" : packageWhiteList;
        _packageWhiteList.addAll(Arrays.asList(packageWhiteList.split("\\,")));

        String additionalClassPath = context.getInitParameter(INIT_PARAM_SCRIPTING_ADDITIONAL_CLASSPATH);
        additionalClassPath = (additionalClassPath == null) ? "" : additionalClassPath;
        String[] additionalClassPaths = additionalClassPath.split("\\,");
        for(String cp: additionalClassPaths) {
            _additionalClassPath.addAll(performWildCardSearch(cp));
        }

        _additionalClassPath.addAll(Arrays.asList(additionalClassPaths));

        String resourcePath = context.getInitParameter(INIT_PARAM_RESOURCE_PATH);
        resourcePath = (resourcePath == null) ? "" : resourcePath;
        _resourceDirs.addAll(Arrays.asList(resourcePath.split("\\,")));

        _initialCompile = context.getInitParameter(INIT_PARAM_INITIAL_COMPILE);
        //_additionalClassPath = context.getInitParameter(INIT_PARAM_SCRIPTING_ADDITIONAL_CLASSPATH);

        for (ScriptingEngine engine : FactoryEngines.getInstance().getEngines())
        {
            engine.init(context);
        }

        _contextWeakReference = new WeakReference<ServletContext>(context);
    }

    public String getFileEnding(int scriptingEngine)
    {
        switch (scriptingEngine)
        {
            case ENGINE_TYPE_JSF_JAVA:
                return JAVA_FILE_ENDING;
            case ENGINE_TYPE_JSF_GROOVY:
                return GROOVY_FILE_ENDING;
            case ENGINETYPE_JSF_JRUBY:
                return JRUBY_FILE_ENDING;
            default:
                throw new UnsupportedOperationException("Engine type unknown");
        }
    }

    public Collection<String> getSourceDirs(int scriptingEngine)
    {
        return WeavingContext.getInstance().getEngine(scriptingEngine).getSourcePaths();
    }

    /**
     * returns a set of whitelisted subdirs hosting the source
     *
     * @param scriptingEngine the scripting engine for which the dirs have to be determined
     *                        (note every scripting engine has a unique integer value)
     * @return the current whitelisted dirs hosting the sources
     */
    public Collection<String> getWhitelistedSourceDirs(int scriptingEngine)
    {
        Collection<String> origSourceDirs = getSourceDirs(scriptingEngine);
        if (_packageWhiteList.isEmpty())
        {
            return origSourceDirs;
        }

        return mergeWhitelisted(origSourceDirs);
    }

    /**
     * merges the whitelisted packages with the sourcedirs and generates a final list
     * which left join of both sets - the ones which do not exist in reality
     *
     * @param origSourceDirs the original source dirs
     * @return the joined existing subset of all directories which exist
     */
    private Collection<String> mergeWhitelisted(Collection<String> origSourceDirs)
    {
        List<String> retVal = new ArrayList<String>(_packageWhiteList.size() * origSourceDirs.size() + origSourceDirs.size());

        for (String whitelisted : _packageWhiteList)
        {
            whitelisted = whitelisted.replaceAll("\\.", FileUtils.getFileSeparatorForRegex());
            for (String sourceDir : origSourceDirs)
            {
                String newSourceDir = sourceDir + File.separator + whitelisted;
                if ((new File(newSourceDir)).exists())
                {
                    retVal.add(newSourceDir);
                }
            }
        }
        return retVal;
    }

    //----------------------- standard setter and getter --------------------------------------

    /**
     * Add a new source dir for the corresponding scripting engine
     *
     * @param scriptingEngine integer value marking the corresponding engine
     * @param sourceDir       the source directory added to the existing source dir list
     */
    public void addSourceDir(int scriptingEngine, String sourceDir)
    {
        if (!WeavingContext.getInstance().getEngine(scriptingEngine).getSourcePaths().contains(sourceDir))
            WeavingContext.getInstance().getEngine(scriptingEngine).getSourcePaths().add(sourceDir);
    }

    public String getSystemClasspath() {
        return System.getProperty("java.class.path");
    }
    
    public List<String> getJarPaths()
    {
        ServletContext context = _contextWeakReference.get();
        Collection<String> relativePaths = _contextWeakReference.get().getResourcePaths("/WEB-INF/lib");
        List<String> ret = new ArrayList<String>(relativePaths.size());
        for (String jarPath : relativePaths)
        {
            try
            {
                ret.add(context.getResource(jarPath).getFile());
            }
            catch (MalformedURLException e)
            {
                e.printStackTrace();
            }
        }
        return ret;
    }

    public List<String> getClassesPaths()
    {
        ServletContext context = _contextWeakReference.get();
        Collection<String> relativePaths = _contextWeakReference.get().getResourcePaths(WEB_INF_CLASSES);
        List<String> ret = new ArrayList<String>(relativePaths.size());
        for (String jarPath : relativePaths)
        {
            try
            {
                String file = context.getResource(jarPath).getFile();
                int pos = file.indexOf(WEB_INF_CLASSES);
                file = file.substring(0, pos + WEB_INF_CLASSES.length());
                ret.add(file);
            }
            catch (MalformedURLException e)
            {
                e.printStackTrace();
            }
        }
        return ret;
    }

    public List<String> getAdditionalClassPath()
    {
        return _additionalClassPath;
    }

    public void setAdditionalClassPath(List<String> additionalClassPath)
    {
        _additionalClassPath = additionalClassPath;
    }

    public void addAdditionalClassPath(String additionalClassPath)
    {
        _additionalClassPath.add(additionalClassPath);
    }

    public Set<String> getPackageWhiteList()
    {
        return _packageWhiteList;
    }

    public void setPackageWhiteList(Set<String> packageWhiteList)
    {
        _packageWhiteList = packageWhiteList;
    }

    public void addWhitelistPackage(String pckg)
    {
        _packageWhiteList.add(pckg);
    }

    public List<String> getResourceDirs()
    {
        return _resourceDirs;
    }

    public void setResourceDirs(List<String> resourceDirs)
    {
        _resourceDirs = resourceDirs;
    }

    public void addResourceDir(String resourceDir)
    {
        _resourceDirs.add(resourceDir);
    }

    public String getInitialCompile()
    {
        return _initialCompile;
    }

    public void setInitialCompile(String initialCompile)
    {
        _initialCompile = initialCompile;
    }

    public File getCompileTarget()
    {
        return _compileTarget;
    }

    public void setCompileTarget(File compileTarget)
    {
        _compileTarget = compileTarget;
    }

}

