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

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 *
 */
public abstract class AbstractTarget implements Target
{
    private static final int INVALID_FILTER_CHARS = 10016;
    private static final int INVALID_FILTER_STAR = 10017;

    protected final String id;
    protected List filters;
    protected volatile short level;
    protected volatile int loggerCount;
    private final Object lock = new Object();
    private boolean usingDefaultFilter = false;

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

    /**
     * Default constructor.
     */
    public AbstractTarget()
    {
        id = UUIDUtils.createUUID();
        level = LogEvent.ERROR;
        filters = new ArrayList();
        filters.add("*");
        usingDefaultFilter = true;
    }

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

    /**
     * Initializes the target with id and properties. Subclasses can overwrite.
     *
     * @param id id for the target which is ignored.
     * @param properties ConfigMap of properties for the target.
     */
    public void initialize(String id, ConfigMap properties)
    {
        // No-op
    }

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

    /**
     * Return a read-only snap-shot of the current filters for this target.
     *
     * @return An unmodifiable list of filters.
     */
    public List getFilters()
    {
        return Collections.unmodifiableList(new ArrayList(filters));
    }

    /**
     * Adds a filter to this target.
     *
     * @param value Filter to be added.
     */
    public void addFilter(String value)
    {
        if (value != null)
            validateFilter(value);
        else // Default to "*"
            value = "*";

        boolean filterWasAdded = false;
        synchronized (lock)
        {
            if (!filters.contains(value))
            {
                // If the default filter is being used, remove it.
                if (usingDefaultFilter)
                {
                    removeFilter("*");
                    usingDefaultFilter = false;
                }
                filters.add(value);
                filterWasAdded = true;
            }
        }
        if (filterWasAdded)
            Log.processTargetFilterAdd(this, value);
    }

    /**
     * Removes a filter from this target.
     *
     * @param value Filter to be removed.
     */
    public void removeFilter(String value)
    {
        boolean filterWasRemoved;
        synchronized (lock)
        {
            filterWasRemoved = filters.remove(value);
        }
        if (filterWasRemoved)
            Log.processTargetFilterRemove(this, value);
    }

    /**
     * Sets the list of filters for this target.
     *
     * @param value List of filters.
     */
    public void setFilters(List value)
    {
        if (value != null && value.size() > 0)
        {
            // a valid filter value will be fully qualified or have a wildcard
            // in it.  the wild card can only be located at the end of the
            // expression.  valid examples  xx*, xx.*,  *
            for (int i = 0; i < value.size(); i++)
            {
                validateFilter((String) value.get(i));
            }
        }
        else
        {
            // if null was specified then default to all
            value = new ArrayList();
            value.add("*");
        }

        Log.removeTarget(this);
        synchronized (lock)
        {
            filters = value;
            usingDefaultFilter = false;
        }
        Log.addTarget(this);
    }

    /**
     * Return the log level for this target.
     *
     * @return the log level set for this target.
     */
    public short getLevel()
    {
        return level;
    }

    /**
     * Return the target's unique ID.
     *
     * @return the target's unique ID.
     */
    public String getId()
    {
        return id;
    }

    /**
     * Sets the log level for this target. If not set, defaults to <code>LogEvent.ERROR</code>.
     */
    public void setLevel(short value)
    {
        level = value;
        Log.resetTargetLevel();
    }

    /**
     * Sets up this target with the specified logger.
     * This allows this target to receive log events from the specified logger.
     *
     * @param logger this target should listen to.
     */
    public void addLogger(Logger logger)
    {
        if (logger != null)
        {
            synchronized (lock)
            {
                loggerCount++;
            }
            logger.addTarget(this);
        }
    }

    /**
     * Stops this target from receiving events from the specified logger.
     *
     * @param logger this target should ignore.
     */
    public void removeLogger(Logger logger)
    {
        if (logger != null)
        {
            synchronized (lock)
            {
                loggerCount--;
            }
            logger.removeTarget(this);
        }
    }

    /**
     * @param filter category to check against the filters defined for this target
     * @return whether filter is defined
     */
    public boolean containsFilter(String filter)
    {
        return filters.contains(filter);
    }

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

    private void validateFilter(String value)
    {
        // check for invalid characters
        if (Log.hasIllegalCharacters(value))
        {
            //Error for filter '{filter}'. The following characters are not valid: {Log.INVALID_CHARS}
            LocalizedException ex = new LocalizedException();
            ex.setMessage(INVALID_FILTER_CHARS, new Object[]{value, Log.INVALID_CHARS});
            throw ex;
        }

        int index = value.indexOf('*');
        if ((index >= 0) && (index != (value.length() - 1)))
        {
            //Error for filter '{filter}'. '*' must be the right most character.
            LocalizedException ex = new LocalizedException();
            ex.setMessage(INVALID_FILTER_STAR, new Object[]{value});
            throw ex;
        }
    }
}
