/*
 *  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.qpid.server.logging;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.File;
import java.io.FileWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.TreeSet;
import java.util.Set;
import java.util.ResourceBundle;

public class GenerateLogMessages
{
    private boolean DEBUG = false;
    private String _tmplDir;
    private String _outputDir;
    private List<String> _logMessages = new LinkedList<String>();
    private String _packageSource;

    public static void main(String[] args)
    {
        GenerateLogMessages generator = null;
        try
        {
            generator = new GenerateLogMessages(args);
        }
        catch (IllegalAccessException iae)
        {
            // This occurs when args does not contain Template and output dirs.
            System.exit(-1);
        }
        catch (Exception e)
        {
            //This is thrown by the Velocity Engine initialisation
            e.printStackTrace();
            System.exit(-1);
        }

        try
        {
            System.out.println("Running LogMessage Generator");
            generator.run();
        }
        catch (InvalidTypeException e)
        {
            // This occurs when a type other than 'number' appears in the paramater config {0, number...}.
            System.err.println(e.getMessage());
            System.exit(-1);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    GenerateLogMessages(String[] args) throws Exception
    {
        processArgs(args);

        // We need the template and input files to run.
        if (_tmplDir == null || _outputDir == null || _logMessages.size() == 0 || _packageSource == null)
        {
            showUsage();
            throw new IllegalAccessException();
        }

        // Initialise the Velocity Engine, Telling it where our macro lives
        Properties props = new Properties();
        props.setProperty("file.resource.loader.path", _tmplDir);
        Velocity.init(props);
    }

    private void showUsage()
    {
        System.out.println("Broker LogMessageGenerator v.2.0");
        System.out.println("Usage: GenerateLogMessages: [-d] -t <Template Dir> -o <Output Root> -s <Source Directory> <List of _logmessage.property files to process>");
        System.out.println("       where -d : Additional debug loggin.\n" +
                           "             Template Dir: Is the base template to use.");
        System.out.println("             Output Root:  The root form where the LogMessage Classes will be placed.");
        System.out.println("             Source Dir :  The root form where the logmessasge.property files can be found.");
        System.out.println("             _logmessage.property files must include the full package structure.");
    }

    public void run() throws InvalidTypeException, Exception
    {
        for (String file : _logMessages)
        {
            debug("Processing File:" + file);

            createMessageClass(file);
        }
    }

    /**
     * Process the args for:
     * -t|T value for the template location
     * -o|O value for the output directory
     *
     * @param args the commandline arguments
     */
    private void processArgs(String[] args)
    {
        // Crude but simple...
        for (int i = 0; i < args.length; i++)
        {
            String arg = args[i];
            if (args[i].endsWith("_logmessages.properties"))
            {
                _logMessages.add(args[i]);
            }
            else if (arg.charAt(0) == '-')
            {
                switch (arg.charAt(1))
                {
                    case 'o':
                    case 'O':
                        if (++i < args.length)
                        {
                            _outputDir = args[i];
                        }
                        break;
                    case 't':
                    case 'T':
                        if (++i < args.length)
                        {
                            _tmplDir = args[i];
                        }
                        break;
                    case 's':
                    case 'S':
                        if (++i < args.length)
                        {
                            _packageSource = args[i];
                        }
                        break;
                    case 'd':
                    case 'D':
                        DEBUG=true;
                        break;
                }
            }
        }
    }

    /**
     * This is the main method that generates the _Messages.java file.
     * The class is generated by extracting the list of messges from the
     * available LogMessages Resource.
     *
     * The extraction is done based on typeIdentifier which is a 3-digit prefix
     * on the messages e.g. BRK for Broker.
     *
     * @throws InvalidTypeException when an unknown parameter type is used in the properties file
     * @throws Exception            thrown by velocity if there is an error
     */
    private void createMessageClass(String file)
            throws InvalidTypeException, Exception
    {
        VelocityContext context = new VelocityContext();

        String bundle = file.replace(File.separator, ".");

        int packageStartIndex = bundle.indexOf(_packageSource) + _packageSource.length() + 2;

        bundle = bundle.substring(packageStartIndex, bundle.indexOf(".properties"));

        System.out.println("Creating Class for bundle:" + bundle);

        ResourceBundle fileBundle = ResourceBundle.getBundle(bundle, Locale.US);

        // Pull the bit from /os/path/<className>.logMessages from the bundle name
        String className = file.substring(file.lastIndexOf(File.separator) + 1, file.lastIndexOf("_"));
        debug("Creating ClassName form file:" + className);

        String packageString = bundle.substring(0, bundle.indexOf(className));
        String packagePath = packageString.replace(".", File.separator);

        debug("Package path:" + packagePath);

        File outputDirectory = new File(_outputDir + File.separator + packagePath);
        if (!outputDirectory.exists())
        {
            if (!outputDirectory.mkdirs())
            {
                throw new IllegalAccessException("Unable to create package structure:" + outputDirectory);
            }
        }

        // Get the Data for this class and typeIdentifier
        HashMap<String, Object> typeData = prepareType(className, fileBundle);

        context.put("package", packageString.substring(0, packageString.lastIndexOf('.')));
        //Store the resource Bundle name for the macro
        context.put("resource", bundle);

        // Store this data in the context for the macro to access
        context.put("type", typeData);

        // Create the file writer to put the finished file in
        String outputFile = _outputDir + File.separator + packagePath + className + "Messages.java";
        debug("Creating Java file:" + outputFile);
        FileWriter output = new FileWriter(outputFile);

        // Run Velocity to create the output file.
        // Fix the default file encoding to 'ISO-8859-1' rather than let
        // Velocity fix it. This is the encoding format for the macro.
        Velocity.mergeTemplate("LogMessages.vm", "ISO-8859-1", context, output);

        //Close our file.
        output.flush();
        output.close();
    }

    /**
     * This method does the processing and preparation of the data to be added
     * to the Velocity context so that the macro can access and process the data
     *
     * The given messageKey (e.g. 'BRK') uses a 3-digit code used to match
     * the property key from the loaded 'LogMessages' ResourceBundle.
     *
     * This gives a list of messages which are to be associated with the given
     * messageName (e.g. 'Broker')
     *
     * Each of the messages in the list are then processed to identify how many
     * parameters the MessageFormat call is expecting. These parameters are
     * identified by braces ('{}') so a quick count of these can then be used
     * to create a defined parameter list.
     *
     * Rather than defaulting all parameters to String a check is performed to
     * see if a 'number' value has been requested. e.g. {0. number}
     * {@see MessageFormat}. If a parameter has a 'number' type then the
     * parameter will be defined as an Number value. This allows for better
     * type checking during compilation whilst allowing the log message to
     * maintain formatting controls.
     *
     * OPTIONS
     *
     * The returned hashMap contains the following structured data:
     *
     * - name - ClassName ('Broker')
     * - list[logEntryData] - methodName ('BRK_1001')
     * - name ('BRK-1001')
     * - format ('Startup : Version: {0} Build: {1}')
     * - parameters (list)
     * - type ('String'|'Number')
     * - name ('param1')
     * - options (list)
     * - name ('opt1')
     * - value ('AutoDelete')
     *
     * @param messsageName the name to give the Class e.g. 'Broker'
     *
     * @return A HashMap with data for the macro
     *
     * @throws InvalidTypeException when an unknown parameter type is used in the properties file
     */
    private HashMap<String, Object> prepareType(String messsageName, ResourceBundle messages) throws InvalidTypeException
    {
        // Load the LogMessages Resource Bundle
        Set<String> messageKeys = new TreeSet<>(messages.keySet());

        //Create the return map
        HashMap<String, Object> messageTypeData = new HashMap<String, Object>();
        // Store the name to give to this Class <name>Messages.java
        messageTypeData.put("name", messsageName);

        // Prepare the list of log messages
        List<HashMap> logMessageList = new LinkedList<HashMap>();
        messageTypeData.put("list", logMessageList);

        //Process each of the properties
        for(String message : messageKeys)
        {
            HashMap<String, Object> logEntryData = new HashMap<String, Object>();

            // Process the log message if it matches the specified key e.g.'BRK_'
            if (!message.equals("package"))
            {
                // Method names can't have a '-' in them so lets make it '_'
                // e.g. RECOVERY-STARTUP -> RECOVERY_STARTUP
                logEntryData.put("methodName", message.replace('-', '_'));
                // Store the real name so we can use that in the actual log.
                logEntryData.put("name", message);

                //Retrieve the actual log message string.
                String logMessage = messages.getString(message);

                // Store the value of the property so we can add it to the
                // Javadoc of the method.
                logEntryData.put("format", logMessage);

                // Add the parameters for this message
                logEntryData.put("parameters", extractParameters(logMessage));

                //Add the options for this messages
                logEntryData.put("options", extractOptions(logMessage));

                //Add this entry to the list for this class
                logMessageList.add(logEntryData);
            }
        }

        return messageTypeData;
    }

    /**
     * This method is responsible for extracting the options form the given log
     * message and providing a HashMap with the expected data:
     * - options (list)
     * - name ('opt1')
     * - value ('AutoDelete')
     *
     * The options list that this method provides must contain HashMaps that
     * have two entries. A 'name' and a 'value' these strings are important as
     * they are used in LogMessage.vm to extract the stored String during
     * processing of the template.
     *
     * The 'name' is a unique string that is used to name the boolean parameter
     * and refer to it later in the method body.
     *
     * The 'value' is used to provide documentation in the generated class to
     * aid readability.
     *
     * @param logMessage the message from the properties file
     *
     * @return list of option data
     */
    private List<HashMap<String, String>> extractOptions(String logMessage)
    {
        // Split the string on the start brace '{' this will give us the
        // details for each parameter that this message contains.
        // NOTE: Simply splitting on '[' prevents the use of nested options.
        // Currently there is no demand for nested options        
        String[] optionString = logMessage.split("\\[");
        // Taking an example of:
        // 'Text {n,type,format} [option] text {m} [option with param{p}] more'
        // This would give us:
        // 0 - Text {n,type,format}.
        // 1 - option] text {m}.
        // 2 - option with param{p}] more.

        // Create the parameter list for this item
        List<HashMap<String, String>> options = new LinkedList<HashMap<String, String>>();

        // Check that we have some parameters to process
        // Skip 0 as that will not be the first entry
        //  Text {n,type,format} [option] text {m} [option with param{p}] more
        if (optionString.length > 1)
        {
            for (int index = 1; index < optionString.length; index++)
            {
                // Use a HashMap to store the type,name of the parameter
                // for easy retrieval in the macro template
                HashMap<String, String> option = new HashMap<String, String>();

                // Locate the end of the Option
                // NOTE: it is this simple matching on the first ']' that
                // prevents the nesting of options.
                // Currently there is no demand for nested options
                int end = optionString[index].indexOf("]");

                // The parameter type
                String value = optionString[index].substring(0, end);

                // Simply name the parameters by index.
                option.put("name", "opt" + index);

                //Store the value e.g. AutoDelete
                // We trim as we don't need to include any whitespace that is
                // used for formating. This is only used to aid readability of
                // of the generated code.
                option.put("value", value.trim());

                options.add(option);
            }
        }

        return options;
    }

    /**
     * This method is responsible for extract the parameters that are requried
     * for this log message. The data is returned in a HashMap that has the
     * following structure:
     * - parameters (list)
     * - type ('String'|'Number')
     * - name ('param1')
     *
     * The parameters list that is provided must contain HashMaps that have the
     * two named entries. A 'type' and a 'name' these strings are importans as
     * they are used in LogMessage.vm to extract and the stored String during
     * processing of the template
     *
     * The 'type' and 'name' values are used to populate the method signature.
     * This is what gives us the compile time validation of log messages.
     *
     * The 'name' must be unique as there may be many parameters. The value is
     * also used in the method body to pass the values through to the
     * MessageFormat class for formating the log message.
     *
     * @param logMessage the message from the properties file
     *
     * @return list of option data
     *
     * @throws InvalidTypeException if the FormatType is specified and is not 'number'
     */
    private List<HashMap<String, String>> extractParameters(String logMessage)
            throws InvalidTypeException
    {
        // Split the string on the start brace '{' this will give us the
        // details for each parameter that this message contains.
        String[] parametersString = logMessage.split("\\{");
        // Taking an example of 'Text {n[,type]} text {m} more text {p}'
        // This would give us:
        // 0 - Text.
        // 1 - n[,type]} text.
        // 2 - m} more text.
        // 3 - p}.

        // Create the parameter list for this item
        List<HashMap<String, String>> parameters = new LinkedList<HashMap<String, String>>();

        /*
          Check that we have some parameters to process
          Skip 0 as that will not be the first entry
          Text {n[,type]} text {m} more text {p}.
        */

        if (parametersString.length > 1)
        {
            for (int index = 1; index < parametersString.length; index++)
            {
                // Use a HashMap to store the type,name of the parameter
                // for easy retrieval in the macro template
                HashMap<String, String> parameter = new HashMap<String, String>();

                /*
                  Check for any properties of the parameter :
                  e.g. {0} vs {0,number} vs {0,number,xxxx}.
                */

                int typeIndex = parametersString[index].indexOf(",");
                int typeIndexEnd = parametersString[index].indexOf("}", typeIndex);
                // The parameter type
                String type;

                //Be default all types are Strings
                if (typeIndex == -1 || typeIndexEnd == -1)
                {
                    type = "String";
                }
                else
                {
                    //Check string ',....}' for existence of number
                    // to identify this parameter as an integer
                    // This allows for a style value to be present
                    // Only check the text inside the braces '{}'
                    String typeString = parametersString[index].substring(typeIndex, typeIndexEnd);
                    if (typeString.contains("number") || typeString.contains("choice"))
                    {
                        type = "Number";
                    }
                    else
                    {
                        throw new InvalidTypeException("Invalid type(" + typeString + ") index (" + parameter.size() + ") in message:" + logMessage);
                    }

                }

                //Store the data
                parameter.put("type", type);
                // Simply name the parameters by index.
                parameter.put("name", "param" + index);

                parameters.add(parameter);
            }
        }

        return parameters;
    }

    /**
     * Just a inner exception to be able to identify when a type that is not
     * 'number' occurs in the message parameter text.
     */
    private static class InvalidTypeException extends Exception
    {
        public InvalidTypeException(String message)
        {
            super(message);
        }
    }

    public void debug(String msg)
    {
        if (DEBUG)
        {
            System.out.println(msg);
        }
    }

}
