/*
 * 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.engine;

import org.apache.commons.io.FilenameUtils;
import org.apache.myfaces.extensions.scripting.core.common.util.ClassUtils;
import org.apache.myfaces.extensions.scripting.core.common.util.FileUtils;
import org.apache.myfaces.extensions.scripting.core.engine.dependencyScan.api.DependencyRegistry;
import org.apache.myfaces.extensions.scripting.core.engine.dependencyScan.core.ClassDependencies;
import org.apache.myfaces.extensions.scripting.core.engine.dependencyScan.registry.DependencyRegistryImpl;
import org.apache.myfaces.extensions.scripting.core.monitor.ClassResource;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

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

public abstract class BaseEngine
{
    Set<String> _sourcePaths = Collections.synchronizedSet(new HashSet<String>());
    Map<String, ClassResource> _watchedResources = new ConcurrentHashMap<String, ClassResource>();
    //both belong together but the dependencyregistry is just
    //a wrapper for the dep map with additional functionality
    ClassDependencies _dependencyMap = new ClassDependencies();
    DependencyRegistry _dependencyRegistry = new DependencyRegistryImpl(getEngineType(), _dependencyMap);

    Logger log = Logger.getLogger(this.getClass().getName());


    protected BaseEngine()
    {

    }

    public Map<String, ClassResource> getWatchedResources()
    {
        return _watchedResources;
    }

    public Collection<String> getSourcePaths()
    {
        return _sourcePaths;
    }

    public abstract String getFileEnding();

    public abstract int getEngineType();

    /**
     * @return a collection of possible dynamic classes
     */
    public Collection<String> getPossibleDynamicClasses()
    {
        return _watchedResources.keySet();
    }

    /**
     * runs a full scan of files to get a list of files which need to be processed
     * for the future
     */
    public void scanForAddedDeleted()
    {
        Set<String> processedClasses = new HashSet<String>();
        processedClasses.addAll(_watchedResources.keySet());

        for (String sourcePath : getSourcePaths())
        {
            Collection<File> sourceFiles = FileUtils.fetchSourceFiles(new File(sourcePath), "*." + getFileEnding());

            for (File sourceFile : sourceFiles)
            {
                ClassResource classToProcess = new ClassResource();
                classToProcess.setFile(sourceFile);


                classToProcess.setScriptingEngine(getEngineType());
                if (!_watchedResources.containsKey(classToProcess.getIdentifier()))
                {
                    _watchedResources.put(classToProcess.getIdentifier(), classToProcess);
                } else
                {
                    processedClasses.remove(classToProcess.getIdentifier());

                    classToProcess = _watchedResources.get(classToProcess.getIdentifier());
                }
                if (classToProcess.needsRecompile())
                {
                    //TODO add entry for logging component here
                    log.info("[EXT-SCRIPTING] tainting " + classToProcess.getIdentifier());
                    classToProcess.setTainted(true);
                    classToProcess.setChangedForCompile(true);
                }
            }
        }
        for (String deleted : processedClasses)
        {
            _watchedResources.remove(deleted);
        }

    }

    /**
     * checks whether we have resources which are in need of a recompile
     *
     * @return true if a recompile is needed
     */
    public boolean needsRecompile()
    {
        //TODO buffer this from scan
        for (Map.Entry<String, ClassResource> resource : _watchedResources.entrySet())
        {
            if (resource.getValue().needsRecompile()) return true;
        }
        return false;
    }

    /**
     * checks whether we have resources which are tainted
     *
     * @return true if any resource is tainted
     */
    public boolean isTainted()
    {
        //TODO buffer this from scan
        for (Map.Entry<String, ClassResource> resource : _watchedResources.entrySet())
        {
            if (resource.getValue().isTainted()) return true;
        }
        return false;
    }

    public DependencyRegistry getDependencyRegistry()
    {
        return _dependencyRegistry;
    }

    public void setDependencyRegistry(DependencyRegistry dependencyRegistry)
    {
        _dependencyRegistry = dependencyRegistry;
    }

    public ClassDependencies getDependencyMap()
    {
        return _dependencyMap;
    }

    public void setDependencyMap(ClassDependencies dependencyMap)
    {
        _dependencyMap = dependencyMap;
    }

    /**
     * marks all the dependencies of the tainted objects
     * also as tainted to allow proper refreshing.
     */
    public void markTaintedDependencies()
    {
        //basic tainted set by the full scall
        Set<String> _processedClasses = new HashSet<String>();
        for (Map.Entry<String, ClassResource> entry : _watchedResources.entrySet())
        {
            //TODO add entry for logging component here
            ClassResource resource = entry.getValue();
            if (!resource.isChangedForCompile()) continue;
            resource.setChangedForCompile(false);
            log.info("[EXT-SCRIPTING] tainting dependency " + resource.getIdentifier());
            resource.setTainted(true);
            //classname
            String identifier = resource.getIdentifier();
            if (_processedClasses.contains(identifier)) continue;
            markDependencies(_processedClasses, identifier);

        }

    }

    /*marks all backward dependencies of the existing class*/
    private void markDependencies(Set<String> _processedClasses, String identifier)
    {
        Set<String> referringClasses = _dependencyMap.getReferringClasses(identifier);
        if (referringClasses == null) return;
        for (String referringClass : referringClasses)
        {
            if (_processedClasses.contains(referringClass)) continue;
            ClassResource toTaint = _watchedResources.get(referringClass);
            if (toTaint == null) continue;
            //TODO add entry for logging component here
            if (toTaint.isTainted())
            {
                log.info("[EXT-SCRIPTING] dependency already tainted:" + toTaint.getIdentifier());
                _processedClasses.add(toTaint.getIdentifier());
                continue;
            }
            toTaint.setTainted(true);
            toTaint.setChangedForCompile(false);
            log.info("[EXT-SCRIPTING] tainting dependency " + toTaint.getIdentifier());
            _processedClasses.add(toTaint.getIdentifier());
            markDependencies(_processedClasses, toTaint.getIdentifier());
        }

    }

    protected void initPaths(ServletContext context, String initParam, String defaultValue)
    {
        String pathSeparatedList = context.getInitParameter(initParam);
        pathSeparatedList = (pathSeparatedList != null) ? pathSeparatedList : defaultValue;
        if (pathSeparatedList.equals(defaultValue))
        {
            URL resource = ClassUtils.getContextClassLoader().getResource("./");
            //in war deployments a problem can occur if not all paths are set
            String path = (resource == null)? "bogusPath" : resource.getPath();

            try
            {
                pathSeparatedList = FilenameUtils.normalize(URLDecoder.decode(path,
                        Charset.defaultCharset().toString())
                        + "../.." + defaultValue);
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
        }
        log.info("[EXT-SCRIPTING]: sourcepaths found: "+pathSeparatedList);
        String[] paths = pathSeparatedList.split(",");
        for (String path : paths)
        {
            getSourcePaths().add(path);
        }
    }
}
