/*
 * 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 flex.messaging.log;

import flex.messaging.LocalizedException;
import flex.messaging.config.ConfigMap;
import flex.messaging.util.PrettyPrinter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.HashSet;

/**
 *
 */
public class Log
{

    public static final String INVALID_CHARS = "[]~$^&\\/(){}<>+=`!#%?,:;\'\"@";

    // Errors
    private static final int INVALID_TARGET = 10013;
    private static final int INVALID_CATEGORY = 10014;
    private static final int INVALID_CATEGORY_CHARS = 10015;

    private static Log log;
    private static PrettyPrinter prettyPrinter;
    private static String prettyPrinterClass = "flex.messaging.util.BasicPrettyPrinter";

    private static final HashSet excludedProperties = new HashSet();
    public static final String VALUE_SUPRESSED = "** [Value Suppressed] **";

    private volatile short targetLevel;
    private final Map loggers;
    private final List targets;
    private final Map targetMap;
    private static final Object staticLock = new Object();


    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Private constructor.
     */
    private Log()
    {
        targetLevel = LogEvent.NONE;
        loggers = new HashMap();
        targets = new ArrayList();
        targetMap = new LinkedHashMap();
    }


    /**
     * Creates the log on first access, returns already created log on
     * subsequent calls.
     *
     * @return log.
     */
    public static Log createLog()
    {
        synchronized (staticLock)
        {
            if (log == null)
                log = new Log();

            return log;
        }
    }

    //--------------------------------------------------------------------------
    //
    // Initialize, validate, start, and stop methods.
    //
    //--------------------------------------------------------------------------

    /**
     * Initializes Log with id and properties.
     *
     * @param id Id for the Log which is ignored, though is used by the ManageableComponent superclass
     * @param properties ConfigMap of properties for the Log.
     */
    public static synchronized void initialize(String id, ConfigMap properties)
    {
        String value = properties.getPropertyAsString("pretty-printer", null);
        if (value != null)
            prettyPrinterClass = value;

        // Create a HashSet with the properties that we want to exclude from the
        // list of properties given by 'getPropertiesAsList'
        ConfigMap excludeMap = properties.getPropertyAsMap("exclude-properties", null);
        if (excludeMap != null)
        {
            if (excludeMap.getPropertyAsList("property", null) != null)
                excludedProperties.addAll(excludeMap.getPropertyAsList("property", null));
        }
    }

    //--------------------------------------------------------------------------
    //
    // Public Getters and Setters for Log properties
    //
    //--------------------------------------------------------------------------

    /**
     * Indicates whether a fatal level log event will be processed by a log target.
     * @return boolean true if it is Fatal level
     */
    public static boolean isFatal()
    {
        return log == null ? false : log.targetLevel <= LogEvent.FATAL;
    }

    /**
     * Indicates whether an error level log event will be processed by a log target.
     * @return boolean true if it is Error level
     */
    public static boolean isError()
    {
        return log == null ? false : log.targetLevel <= LogEvent.ERROR;
    }

    /**
     * Indicates whether a warn level log event will be processed by a log target.
     * @return boolean true if it is Warn level
     */
    public static boolean isWarn()
    {
        return log == null ? false : log.targetLevel <= LogEvent.WARN;
    }

    /**
     * Indicates whether an info level log event will be processed by a log target.
     * @return boolean true if it is Info level
     */
    public static boolean isInfo()
    {
        return log == null ? false : log.targetLevel <= LogEvent.INFO;
    }

    /**
     * Indicates whether a debug level log event will be processed by a log target.
     * @return boolean true if it is debug level
     */
    public static boolean isDebug()
    {
        return log == null ? false : log.targetLevel <= LogEvent.DEBUG;
    }

    /**
     * Indicates whether a log property should be excluded.
     * @param property the property to check
     * @return boolean true if the property should be excluded
     */
    public static boolean isExcludedProperty(String property)
    {
        return !excludedProperties.isEmpty() && excludedProperties.contains(property);
    }


    /**
     * Given a category, returns the logger associated with the category.
     *
     * @param category Categogry for the logger.
     * @return Logger associated with the category.
     */
    public static Logger getLogger(String category)
    {
        if (log != null)
            return getLogger(log, category);

        // Return a dummy logger?
        return new Logger(category);
    }

    /**
     * @param log base logger.
     * @param category category to log to.
     * @return Logger instance for the given category.
     */
    public static Logger getLogger(Log log, String category)
    {
        checkCategory(category);

        synchronized (staticLock)
        {
            Logger result = (Logger) log.loggers.get(category);
            if (result == null)
            {
                result = new Logger(category);

                // Check to see if there are any targets for this logger.
                for (Iterator iter = log.targets.iterator(); iter.hasNext();)
                {
                    Target target = (Target) iter.next();
                    if (categoryMatchInFilterList(category, target.getFilters()))
                        target.addLogger(result);
                }

                log.loggers.put(category, result);
            }
            return result;
        }
    }

    /**
     * Returns an unmodifiable snapshot of the targets registered with this Log when the
     * method is invoked.
     * @return List the list of targets 
     */
    public static List getTargets()
    {
        if (log != null)
        {
            List currentTargets;
            // Snapshot the current target list (shallow copy) and return it.
            synchronized (staticLock)
            {
                currentTargets = Collections.unmodifiableList(new ArrayList(log.targets));
            }
            return currentTargets;
        }
        return null;
    }

    /**
     * Return the Log's map of targets keyed on their human-readable ids (e.g. ConsoleTarget0, ConsoleTarget1, etc.)
     * @return Map the target map
     */
    public static Map getTargetMap()
    {
        if (log != null)
        {
            Map currentTargets;
            synchronized (staticLock)
            {
                currentTargets = new LinkedHashMap(log.targetMap);
            }
            return currentTargets;
        }
        return null;
    }

    /**
     * Returns the target associated with the unique ID searchId.  Returns null if no
     * such target exists.
     * @param searchId the search ID
     * @return Target the associated target
     */
    public static Target getTarget(String searchId)
    {
        if (log != null)
        {
            synchronized (staticLock)
            {
                return (Target) log.targetMap.get(searchId);
            }
        }

        return null;
    }

    /**
     * Return the categories for all of the loggers
     * @return String[] the categories for all of the loggers
     */
    public String[] getLoggers()
    {
        String[] currentCategories;
        if (log != null)
        {
            synchronized (staticLock)
            {
                Object[] currentCategoryObjects = loggers.keySet().toArray();
                currentCategories = new String[currentCategoryObjects.length];
                for (int i = 0; i < currentCategoryObjects.length; i++)
                {
                    currentCategories[i] = (String)(currentCategoryObjects[i]);
                }
            }
        }
        else
        {
            currentCategories = new String[0];
        }

        return currentCategories;
    }

    /**
     * Adds a target to the log.
     *
     * @param target Target to be added.
     */
    public static void addTarget(Target target)
    {
        if (log != null)
        {
            if (target != null)
            {
                synchronized (staticLock)
                {
                    List filters = target.getFilters();

                    // need to find what filters this target matches and set the specified
                    // target as a listener for that logger.
                    Iterator it = log.loggers.keySet().iterator();
                    while (it.hasNext())
                    {
                        String key = (String) it.next();
                        if (categoryMatchInFilterList(key, filters))
                            target.addLogger((Logger) log.loggers.get(key));
                    }
                    // if we found a match all is good, otherwise we need to
                    // put the target in a waiting queue in the event that a logger
                    // is created that this target cares about.
                    if (!log.targets.contains(target))
                        log.targets.add(target);

                    if (!log.targetMap.containsValue(target))
                    {
                        String name = target.getClass().getName();

                        if (name.indexOf(".") > -1)
                        {
                            String[] classes = name.split("\\.");
                            name = classes[classes.length - 1];
                        }

                        log.targetMap.put(new String(name + log.targetMap.size()), target);
                    }

                    // update our global target log level if this target is more verbose.
                    short targetLevel = target.getLevel();
                    if (log.targetLevel == LogEvent.NONE)
                        log.targetLevel = targetLevel;
                    else if (targetLevel < log.targetLevel)
                    {
                        log.targetLevel = targetLevel;
                    }
                }
            }
            else
            {
                // Invalid target specified. Target must not be null.
                LocalizedException ex = new LocalizedException();
                ex.setMessage(INVALID_TARGET);
                throw ex;
            }
        }
    }

    /**
     * Removes a target from the log.
     *
     * @param target The target to be removed.
     */
    public static void removeTarget(Target target)
    {
        if (log != null)
        {
            if (target != null)
            {
                synchronized (staticLock)
                {
                    // Remove the target from any associated loggers.
                    List filters = target.getFilters();
                    Iterator it = log.loggers.keySet().iterator();
                    while (it.hasNext())
                    {
                        String key = (String) it.next();
                        if (categoryMatchInFilterList(key, filters))
                            target.removeLogger((Logger) log.loggers.get(key));
                    }
                    // Remove the target from the Log set.
                    log.targets.remove(target);
                    resetTargetLevel();
                }
            }
            else
            {
                // Invalid target specified. Target must not be null.
                LocalizedException ex = new LocalizedException();
                ex.setMessage(INVALID_TARGET);
                throw ex;
            }
        }
    }

    //--------------------------------------------------------------------------
    //
    // Other Public APIs
    //
    //--------------------------------------------------------------------------

    /**
     * This method removes all of the current loggers and targets from the cache.
     * and resets target level.
     */
    public static synchronized void reset()
    {
        flush();
    }

    /**
     *
     */
    public static void flush()
    {
        if (log != null)
        {
            log.loggers.clear();
            log.targets.clear();
            log.targetLevel = LogEvent.NONE;
        }
    }

    /**
     * @param l string representation of the log level.
     * @return a short value representing the log level.
     */
    public static short readLevel(String l)
    {
        short lvl = LogEvent.ERROR;
        if ((l != null) && (l.length() > 0))
        {
            l = l.trim().toLowerCase();
            char c = l.charAt(0);
            switch (c)
            {
                case 'n':
                    lvl = LogEvent.NONE;
                    break;
                case 'e':
                    lvl = LogEvent.ERROR;
                    break;
                case 'w':
                    lvl = LogEvent.WARN;
                    break;
                case 'i':
                    lvl = LogEvent.INFO;
                    break;
                case 'd':
                    lvl = LogEvent.DEBUG;
                    break;
                case 'a':
                    lvl = LogEvent.ALL;
                    break;
                default:
                    lvl = LogEvent.ERROR;
            }
        }

        return lvl;
    }

    /**
     *
     * This method checks the specified string value for illegal characters.
     *
     * @param value to check for illegal characters.
     *              The following characters are not valid:
     *              []~$^&amp;\/(){}&lt;&gt;+=`!#%?,:;'"&amp;#64;
     * @return <code>true</code> if there are any illegal characters found,
     *         <code>false</code> otherwise
     */
    public static boolean hasIllegalCharacters(String value)
    {
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++)
        {
            char c = chars[i];
            if (INVALID_CHARS.indexOf(c) != -1)
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the PrettyPrinter used by the Log.
     *
     * @return the PrettyPrinter used by the Log.
     */
    public static PrettyPrinter getPrettyPrinter()
    {
        if (prettyPrinter == null ||
                !prettyPrinter.getClass().getName().equals(prettyPrinterClass))
        {
            try
            {
                Class c = Class.forName(prettyPrinterClass);
                prettyPrinter = (PrettyPrinter)c.newInstance();
            }
            catch (Throwable t)
            {
                throw new RuntimeException("Error creating instance of default pretty printer.", t);
            }
        }
        return (PrettyPrinter)prettyPrinter.copy();
    }

    /**
     * Returns the current target level for the Log.
     *
     * @return the current target level for the Log.
     */
    public static short getTargetLevel()
    {
        return log == null ? LogEvent.NONE : log.targetLevel;
    }

    /**
     *
     * Sets the pretty printer class name used by the log.
     *
     * @param value Name of the pretty printer class.
     */
    public static void setPrettyPrinterClass(String value)
    {
        prettyPrinterClass = value;
    }

    //--------------------------------------------------------------------------
    //
    // Protected/private methods.
    //
    //--------------------------------------------------------------------------

    /* package */ static void resetTargetLevel()
    {
        if (log != null)
        {
            synchronized (staticLock)
            {
                short maxTargetLevel = LogEvent.NONE;
                for (Iterator iter = log.targets.iterator(); iter.hasNext();)
                {
                    short targetLevel = ((Target) iter.next()).getLevel();
                    if (maxTargetLevel == LogEvent.NONE || targetLevel < maxTargetLevel)
                        maxTargetLevel = targetLevel;
                }
                log.targetLevel = maxTargetLevel;
            }
        }
    }

    /* package */ static void processTargetFilterAdd(Target target, String filter)
    {
        if (log != null)
        {
            synchronized (staticLock)
            {
                List filters = new ArrayList();
                filters.add(filter);

                // Find the loggers this target matches and add the
                // target as a listener for log events from these loggers.
                Iterator it = log.loggers.keySet().iterator();
                while (it.hasNext())
                {
                    String key = (String) it.next();
                    if (categoryMatchInFilterList(key, filters))
                        target.addLogger((Logger) log.loggers.get(key));
                }
            }
        }
    }

    /* package */ static void processTargetFilterRemove(Target target, String filter)
    {
        if (log != null)
        {
            synchronized (staticLock)
            {
                // Remove the target from any matching loggers.
                List filters = new ArrayList();
                filters.add(filter);
                Iterator it = log.loggers.keySet().iterator();
                while (it.hasNext())
                {
                    String key = (String) it.next();
                    if (categoryMatchInFilterList(key, filters))
                        target.removeLogger((Logger) log.loggers.get(key));
                }
            }
        }
    }

    /**
     * This method checks that the specified category matches any of the filter
     * expressions provided in the filters array.
     *
     * @param category to match against
     * @param filters  - list of strings to check category against.
     * @return <code>true</code> if the specified category matches any of the
     *         filter expressions found in the filters list, <code>false</code>
     *         otherwise.
     */
    private static boolean categoryMatchInFilterList(String category, List filters)
    {
        if (filters == null)
            return false;

        for (int i = 0; i < filters.size(); i++)
        {
            String filter = (String) filters.get(i);
            // match category to filter based on the presence of a wildcard
            if (checkFilterToCategory(filter,category))
                return true;
        }
        return false;
    }

    /**
     * Check whether the category match with the filter.
     * @param filter The filter string to check against a specific category
     * @param category The category which the filter could match
     * @return whether the filter matches a specific category
     */
    public static boolean checkFilterToCategory(String filter, String category)
    {
        int index = -1;
        index = filter.indexOf("*");

        if (index == 0) // match all
        {
            return true;
        }
        else if (index < 0) // match full category to filter
        {
            if (category.equals(filter))
            {
                return true;
            }
        }
        else // match partial category to filter
        {
            if ((category.length() >= index) && category.substring(0, index).equals(filter.substring(0, index)))
            {
                return true;
            }
        }

        return false;
    }

    /**
     * This method will ensure that a valid category string has been specified.
     * If the category is not valid an exception will be thrown.
     *
     * Categories can not contain any blanks or any of the following characters:
     * []`*~,!#$%^&amp;()]{}+=\|'";?&gt;&lt;./&amp;#64; or be less than 1 character in length.
     */
    private static void checkCategory(String category)
    {
        if (category == null || category.length() == 0)
        {
            // Categories must be at least one character in length.
            LocalizedException ex = new LocalizedException();
            ex.setMessage(INVALID_CATEGORY);
            throw ex;
        }

        if (hasIllegalCharacters(category) || (category.indexOf("*") != -1))
        {
            // Categories can not contain any of the following characters: 'INVALID_CHARS'
            LocalizedException ex = new LocalizedException();
            ex.setMessage(INVALID_CATEGORY_CHARS, new Object[]{INVALID_CHARS});
            throw ex;
        }
    }

    /**
     * Clean up static member variables.
     */
    public static void clear()
    {
        log = null;
        prettyPrinter = null;
    }

}
