/*
 * 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.log4j.chainsaw.color;

import org.apache.log4j.chainsaw.ChainsawConstants;
import org.apache.log4j.chainsaw.prefs.SettingsManager;
import org.apache.log4j.rule.ColorRule;
import org.apache.log4j.rule.ExpressionRule;
import org.apache.log4j.rule.Rule;

import java.awt.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.List;
import org.apache.commons.configuration2.AbstractConfiguration;
import org.apache.log4j.chainsaw.logevents.ChainsawLoggingEvent;


/**
 * A colorizer supporting an ordered collection of ColorRules, including support for notification of
 * color rule changes via a propertyChangeListener and the 'colorrule' property.
 *
 * @author Scott Deboy &lt;sdeboy@apache.org&gt;
 */
public class RuleColorizer implements Colorizer {
    private Map<String,List<ColorRule>> rules;
    private final PropertyChangeSupport colorChangeSupport =
        new PropertyChangeSupport(this);
    private Map<String,List<ColorRule>> defaultRules = new HashMap<>();
    private String currentRuleSet = ChainsawConstants.DEFAULT_COLOR_RULE_NAME;
    private Rule findRule;
    private Rule loggerRule;

    private static final String COLORS_EXTENSION = ".colors";

    private final Color WARN_DEFAULT_COLOR = new Color(255, 255, 153);
    private final Color FATAL_OR_ERROR_DEFAULT_COLOR = new Color(255, 153, 153);
    private final Color MARKER_DEFAULT_COLOR = new Color(153, 255, 153);

    private final String DEFAULT_WARN_EXPRESSION = "level == WARN";
    private final String DEFAULT_FATAL_ERROR_EXCEPTION_EXPRESSION = "level == FATAL || level == ERROR || exception exists";
    private final String DEFAULT_MARKER_EXPRESSION = "prop.marker exists";

    public RuleColorizer() {
        List<ColorRule> rulesList = new ArrayList<>();

        String expression = DEFAULT_FATAL_ERROR_EXCEPTION_EXPRESSION;
        rulesList.add(
            new ColorRule(
                expression, ExpressionRule.getRule(expression), FATAL_OR_ERROR_DEFAULT_COLOR,
                Color.black));
        expression = DEFAULT_WARN_EXPRESSION;
        rulesList.add(
            new ColorRule(
                expression, ExpressionRule.getRule(expression), WARN_DEFAULT_COLOR,
                Color.black));

        expression = DEFAULT_MARKER_EXPRESSION;
        rulesList.add(
            new ColorRule(
                expression, ExpressionRule.getRule(expression), MARKER_DEFAULT_COLOR,
                Color.black));

        defaultRules.put(currentRuleSet, rulesList);
        setRules(defaultRules);
    }

    public void setLoggerRule(Rule loggerRule) {
        this.loggerRule = loggerRule;
        colorChangeSupport.firePropertyChange("colorrule", false, true);
    }

    public void setFindRule(Rule findRule) {
        this.findRule = findRule;
        colorChangeSupport.firePropertyChange("colorrule", false, true);
    }

    public Rule getFindRule() {
        return findRule;
    }

    public Rule getLoggerRule() {
        return loggerRule;
    }

    public void setRules(Map<String,List<ColorRule>> rules) {
        this.rules = rules;
        colorChangeSupport.firePropertyChange("colorrule", false, true);
    }

    public Map<String,List<ColorRule>> getRules() {
        return rules;
    }

    public List<ColorRule> getCurrentRules() {
        return rules.get(currentRuleSet);
    }

    public void addRules(Map<String,List<ColorRule>> newRules) {

        for (Map.Entry<String,List<ColorRule>> entry : newRules.entrySet()) {

            if (rules.containsKey(entry.getKey())) {
                rules.get(entry.getKey()).addAll( entry.getValue() );
            } else {
                rules.put(entry.getKey(), entry.getValue());
            }
        }

        colorChangeSupport.firePropertyChange("colorrule", false, true);
    }

    public void addRule(String ruleSetName, ColorRule rule) {
        if (rules.containsKey(ruleSetName)) {
            rules.get(ruleSetName).add(rule);
        } else {
            List<ColorRule> list = new ArrayList<>();
            list.add(rule);
            rules.put(ruleSetName, list);
        }

        colorChangeSupport.firePropertyChange("colorrule", false, true);
    }

    public void removeRule(String ruleSetName, String expression) {
        if (rules.containsKey(ruleSetName)) {
            List<ColorRule> list = rules.get(ruleSetName);

            for (int i = 0; i < list.size(); i++) {
                ColorRule rule = list.get(i);

                if (rule.getExpression().equals(expression)) {
                    list.remove(rule);

                    return;
                }
            }
        }
    }

    public void setCurrentRuleSet(String ruleSetName) {
        currentRuleSet = ruleSetName;
    }

    public Color getBackgroundColor(ChainsawLoggingEvent event) {
        if (rules.containsKey(currentRuleSet)) {
            List<ColorRule> list = rules.get(currentRuleSet);

            for (ColorRule rule : list) {

                if ((rule.getBackgroundColor() != null) && (rule.evaluate(event, null))) {
                    return rule.getBackgroundColor();
                }
            }
        }

        return null;
    }

    public Color getForegroundColor(ChainsawLoggingEvent event) {
        if (rules.containsKey(currentRuleSet)) {
            List<ColorRule> list = rules.get(currentRuleSet);

            for (ColorRule rule : list) {

                if ((rule.getForegroundColor() != null) && (rule.evaluate(event, null))) {
                    return rule.getForegroundColor();
                }
            }
        }

        return null;
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        colorChangeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        colorChangeSupport.removePropertyChangeListener(listener);
    }

    /**
     * @param propertyName
     * @param listener
     */
    public void addPropertyChangeListener(
        String propertyName, PropertyChangeListener listener) {
        colorChangeSupport.addPropertyChangeListener(propertyName, listener);
    }


    /**
     * Save panel color settings
     */
    public void saveColorSettings(String name) {
        ObjectOutputStream o = null;
        try {
            File f = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(name + COLORS_EXTENSION));

            o = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));

            o.writeObject(getRules());
            o.flush();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            try {
                if (o != null) {
                    o.close();
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * Load panel color settings if they exist from the given configuration - otherwise, load default color settings
     */
    public void loadColorSettings(String name){}
    
    public void loadColorSettings(AbstractConfiguration configuration) {
        // When we save/load the rule, we really need to load a map of rules
        // There's no real good way to do this, so we will do this the somewhat
        // dumb way and just load up to 32 color rules, since that seems like
        // a good number
        // This needs to be done for each rule set, so we first need to get a
        // list of the rule sets
        String[] ruleSets = configuration.getStringArray( "color.rulesets" );
        if( ruleSets.length == 0 ){
            // Default rule set is already defined
            return;
        }

        /*
        ColorRule(final String expression,
                   final Rule rule,
                   final Color backgroundColor,
                   final Color foregroundColor)
        */
//        Map<String,List<ColorRule>> rules = new HashMap<>();
//        for( String ruleSet : ruleSets ){
//            String[] rulesForRuleSet = configuration.getStringArray( "color.rules." + ruleSet );
//            for( String individualRule : rulesForRuleSet ){
//
//            }
//        }
//
//        setRules(rules);
    }

    private boolean doLoadColorSettings(String name) {
        //first attempt to load encoded file
        File f = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(name) + COLORS_EXTENSION);

        if (f.exists()) {
            ObjectInputStream s = null;

            try {
                s = new ObjectInputStream(
                    new BufferedInputStream(new FileInputStream(f)));

                Map map = (Map) s.readObject();
                setRules(map);
            } catch (EOFException eof) { //end of file - ignore..
            } catch (IOException ioe) {
                ioe.printStackTrace();
                //unable to load file - delete it
                f.delete();
            } catch (ClassNotFoundException cnfe) {
                cnfe.printStackTrace();
            } finally {
                if (s != null) {
                    try {
                        s.close();
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }
                }
            }
        }
        return f.exists();
    }

    public Vector getDefaultColors() {
        Vector vec = new Vector();

        vec.add(Color.white);
        vec.add(Color.black);
        //add default alternating color & search backgrounds (both foreground are black)
        vec.add(ChainsawConstants.COLOR_ODD_ROW_BACKGROUND);
        vec.add(ChainsawConstants.FIND_LOGGER_BACKGROUND);

        vec.add(new Color(255, 255, 225));
        vec.add(new Color(255, 225, 255));
        vec.add(new Color(225, 255, 255));
        vec.add(new Color(255, 225, 225));
        vec.add(new Color(225, 255, 225));
        vec.add(new Color(225, 225, 255));
        vec.add(new Color(225, 225, 183));
        vec.add(new Color(225, 183, 225));
        vec.add(new Color(183, 225, 225));
        vec.add(new Color(183, 225, 183));
        vec.add(new Color(183, 183, 225));
        vec.add(new Color(232, 201, 169));
        vec.add(new Color(255, 255, 153));
        vec.add(new Color(255, 153, 153));
        vec.add(new Color(189, 156, 89));
        vec.add(new Color(255, 102, 102));
        vec.add(new Color(255, 177, 61));
        vec.add(new Color(61, 255, 61));
        vec.add(new Color(153, 153, 255));
        vec.add(new Color(255, 153, 255));

        return vec;
    }

}
