/*******************************************************************************
 * Copyright (c) 2006, 2007 IBM Corporation and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.releng.build.tools.convert.dom;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.ChoiceFormat;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Map;

import org.eclipse.releng.build.tools.convert.ant.Converter;
import org.eclipse.releng.build.tools.convert.ant.Messages;

public abstract class AbstractDOMConverter implements IDOMConverter {

    public static final HashSet FILTERED_WARNINGS_IDS;

    public static final String  FORBIDDEN_REFERENCE   = "ForbiddenReference";  //$NON-NLS-1$
    public static final String  DISCOURAGED_REFERENCE = "DiscouragedReference"; //$NON-NLS-1$

    static {
        FILTERED_WARNINGS_IDS = new HashSet();
        FILTERED_WARNINGS_IDS.add(FORBIDDEN_REFERENCE);
        FILTERED_WARNINGS_IDS.add(DISCOURAGED_REFERENCE);
    }

    protected Messages          messages;

    private String convertToHTML(final String s) {
        final StringBuffer buffer = new StringBuffer();
        for (int i = 0, max = s.length(); i < max; i++) {
            final char c = s.charAt(i);
            switch (c) {
                case '<':
                    buffer.append("&lt;"); //$NON-NLS-1$
                    break;
                case '>':
                    buffer.append("&gt;"); //$NON-NLS-1$
                    break;
                case '\"':
                    buffer.append("&quot;"); //$NON-NLS-1$
                    break;
                case '&':
                    buffer.append("&amp;"); //$NON-NLS-1$
                    break;
                case '^':
                    buffer.append("&and;"); //$NON-NLS-1$
                    break;
                default:
                    buffer.append(c);
            }
        }
        return String.valueOf(buffer);
    }

    public void dump(final int formatVersion, final Map options, final LogDocumentNode documentNode) {
        switch (formatVersion) {
            case Converter.FORMAT_VERSION_2:
                dumpVersion2(options, documentNode);
        }
    }

    private void dumpVersion2(final Map options, final LogDocumentNode documentNode) {
        final String fileName = (String) options.get(Converter.OUTPUT_FILE_NAME);
        final ProblemSummaryNode summaryNode = documentNode.getSummaryNode();
        if ((summaryNode == null) || ((summaryNode.numberOfErrors == 0) && (summaryNode.numberOfWarnings == 0))) {
            return;
        }
        try {
            final Writer writer = new BufferedWriter(new FileWriter(fileName));
            final String pluginName = extractPluginName(fileName);
            if (pluginName == null) {
                writer.write(messages.getString("header")); //$NON-NLS-1$
            } else {
                final String pattern = messages.getString("dom_header"); //$NON-NLS-1$
                writer.write(MessageFormat.format(pattern,
                        new Object[] { pluginName, extractXmlFileName((String) options.get(Converter.INPUT_SOURCE)) }));
            }
            final ProblemSummaryNode problemSummaryNode = summaryNode;
            writeTopAnchor(writer);
            String pattern = messages.getString("problem.summary"); //$NON-NLS-1$
            writer.write(MessageFormat.format(pattern, new Object[] { Integer.toString(problemSummaryNode.numberOfProblems),
                    Integer.toString(problemSummaryNode.numberOfErrors), Integer.toString(problemSummaryNode.numberOfWarnings) }));

            writeAnchorsReferences(writer);
            final ProblemsNode[] problemsNodes = documentNode.getProblems();
            int globalErrorNumber = 1;

            writeErrorAnchor(writer);
            writeAnchorsReferencesErrors(writer);
            // dump errors
            for (int i = 0, max = problemsNodes.length; i < max; i++) {
                final ProblemsNode problemsNode = problemsNodes[i];
                final ProblemNode[] problemNodes = problemsNode.getErrors();
                final int length = problemNodes.length;
                if (length == 0) {
                    continue;
                }
                pattern = messages.getString("errors.header"); //$NON-NLS-1$

                final MessageFormat form = new MessageFormat(pattern);
                final double[] warningsLimits = { 1, 2 };
                final String[] warningParts = { messages.getString("one_error"), //$NON-NLS-1$
                        messages.getString("multiple_errors") //$NON-NLS-1$
                };
                final ChoiceFormat warningForm = new ChoiceFormat(warningsLimits, warningParts);
                final String sourceFileName = extractRelativePath(problemsNode.sourceFileName, pluginName);
                form.setFormatByArgumentIndex(1, warningForm);
                final Object[] arguments = new Object[] { sourceFileName, new Integer(problemsNode.numberOfErrors), };
                writer.write(form.format(arguments));
                for (int j = 0; j < length; j++) {
                    final ProblemNode problemNode = problemNodes[j];
                    if ((j & 1) != 0) {
                        pattern = messages.getString("errors.entry.odd"); //$NON-NLS-1$
                    } else {
                        pattern = messages.getString("errors.entry.even"); //$NON-NLS-1$
                    }
                    problemNode.setSources();
                    writer.write(MessageFormat.format(
                            pattern,
                            new Object[] { sourceFileName, Integer.toString(globalErrorNumber), Integer.toString(j + 1),
                                    problemNode.id, Integer.toString(problemNode.line), convertToHTML(problemNode.message),
                                    convertToHTML(problemNode.sourceCodeBefore), convertToHTML(problemNode.sourceCode),
                                    convertToHTML(problemNode.sourceCodeAfter),
                                    getUnderLine(problemNode.sourceCodeBefore, problemNode.sourceCodeAfter),
                                    Integer.toString(problemNode.charStart), Integer.toString(problemNode.charEnd), }));
                    globalErrorNumber++;
                }
                writer.write(messages.getString("errors.footer")); //$NON-NLS-1$
            }

            writeOtherWarningsAnchor(writer);
            writeAnchorsReferencesOtherWarnings(writer);
            // dump other warnings
            for (int i = 0, max = problemsNodes.length; i < max; i++) {
                final ProblemsNode problemsNode = problemsNodes[i];
                final ProblemNode[] problemNodes = problemsNode.getOtherWarnings();
                final int length = problemNodes.length;
                if (length == 0) {
                    continue;
                }

                pattern = messages.getString("other_warnings.header"); //$NON-NLS-1$
                final MessageFormat form = new MessageFormat(pattern);
                final double[] warningsLimits = { 1, 2 };
                final String[] warningParts = { messages.getString("one_warning"),//$NON-NLS-1$
                        messages.getString("multiple_warnings") //$NON-NLS-1$
                };
                final ChoiceFormat warningForm = new ChoiceFormat(warningsLimits, warningParts);
                final String sourceFileName = extractRelativePath(problemsNode.sourceFileName, pluginName);
                form.setFormatByArgumentIndex(1, warningForm);
                final Object[] arguments = new Object[] { sourceFileName, new Integer(problemsNode.numberOfWarnings), };
                writer.write(form.format(arguments));
                for (int j = 0; j < length; j++) {
                    final ProblemNode problemNode = problemNodes[j];
                    if ((j & 1) != 0) {
                        pattern = messages.getString("warnings.entry.odd"); //$NON-NLS-1$
                    } else {
                        pattern = messages.getString("warnings.entry.even"); //$NON-NLS-1$
                    }
                    problemNode.setSources();
                    writer.write(MessageFormat.format(
                            pattern,
                            new Object[] { sourceFileName, Integer.toString(globalErrorNumber), Integer.toString(j + 1),
                                    problemNode.id, Integer.toString(problemNode.line), convertToHTML(problemNode.message),
                                    convertToHTML(problemNode.sourceCodeBefore), convertToHTML(problemNode.sourceCode),
                                    convertToHTML(problemNode.sourceCodeAfter),
                                    getUnderLine(problemNode.sourceCodeBefore, problemNode.sourceCodeAfter),
                                    Integer.toString(problemNode.charStart), Integer.toString(problemNode.charEnd), }));
                    globalErrorNumber++;
                }
                writer.write(messages.getString("other_warnings.footer")); //$NON-NLS-1$
            }

            // dump forbidden accesses warnings
            writeForbiddenRulesWarningsAnchor(writer);
            writeAnchorsReferencesForbiddenRulesWarnings(writer);
            for (int i = 0, max = problemsNodes.length; i < max; i++) {
                final ProblemsNode problemsNode = problemsNodes[i];
                final ProblemNode[] problemNodes = problemsNode.getForbiddenWarnings();
                final int length = problemNodes.length;
                if (length == 0) {
                    continue;
                }

                pattern = messages.getString("forbidden_warnings.header"); //$NON-NLS-1$
                final MessageFormat form = new MessageFormat(pattern);
                final double[] warningsLimits = { 1, 2 };
                final String[] warningParts = { messages.getString("one_warning"),//$NON-NLS-1$
                        messages.getString("multiple_warnings") //$NON-NLS-1$
                };
                final ChoiceFormat warningForm = new ChoiceFormat(warningsLimits, warningParts);
                final String sourceFileName = extractRelativePath(problemsNode.sourceFileName, pluginName);
                form.setFormatByArgumentIndex(1, warningForm);
                final Object[] arguments = new Object[] { sourceFileName, new Integer(problemsNode.numberOfWarnings), };
                writer.write(form.format(arguments));
                for (int j = 0; j < length; j++) {
                    final ProblemNode problemNode = problemNodes[j];
                    if ((j & 1) != 0) {
                        pattern = messages.getString("warnings.entry.odd"); //$NON-NLS-1$
                    } else {
                        pattern = messages.getString("warnings.entry.even"); //$NON-NLS-1$
                    }
                    problemNode.setSources();
                    writer.write(MessageFormat.format(
                            pattern,
                            new Object[] { sourceFileName, Integer.toString(globalErrorNumber), Integer.toString(j + 1),
                                    problemNode.id, Integer.toString(problemNode.line), convertToHTML(problemNode.message),
                                    convertToHTML(problemNode.sourceCodeBefore), convertToHTML(problemNode.sourceCode),
                                    convertToHTML(problemNode.sourceCodeAfter),
                                    getUnderLine(problemNode.sourceCodeBefore, problemNode.sourceCodeAfter),
                                    Integer.toString(problemNode.charStart), Integer.toString(problemNode.charEnd), }));
                    globalErrorNumber++;
                }
                writer.write(messages.getString("forbidden_warnings.footer")); //$NON-NLS-1$
            }

            // dump discouraged accesses warnings
            writeDiscouragedRulesWarningsAnchor(writer);
            writeAnchorsReferencesDiscouragedRulesWarnings(writer);
            for (int i = 0, max = problemsNodes.length; i < max; i++) {
                final ProblemsNode problemsNode = problemsNodes[i];
                final ProblemNode[] problemNodes = problemsNode.getDiscouragedWarnings();
                final int length = problemNodes.length;
                if (length == 0) {
                    continue;
                }

                pattern = messages.getString("discouraged_warnings.header"); //$NON-NLS-1$
                final MessageFormat form = new MessageFormat(pattern);
                final double[] warningsLimits = { 1, 2 };
                final String[] warningParts = { messages.getString("one_warning"),//$NON-NLS-1$
                        messages.getString("multiple_warnings") //$NON-NLS-1$
                };
                final ChoiceFormat warningForm = new ChoiceFormat(warningsLimits, warningParts);
                final String sourceFileName = extractRelativePath(problemsNode.sourceFileName, pluginName);
                form.setFormatByArgumentIndex(1, warningForm);
                final Object[] arguments = new Object[] { sourceFileName, new Integer(problemsNode.numberOfWarnings), };
                writer.write(form.format(arguments));
                for (int j = 0; j < length; j++) {
                    final ProblemNode problemNode = problemNodes[j];
                    if ((j & 1) != 0) {
                        pattern = messages.getString("warnings.entry.odd"); //$NON-NLS-1$
                    } else {
                        pattern = messages.getString("warnings.entry.even"); //$NON-NLS-1$
                    }
                    problemNode.setSources();
                    writer.write(MessageFormat.format(
                            pattern,
                            new Object[] { sourceFileName, Integer.toString(globalErrorNumber), Integer.toString(j + 1),
                                    problemNode.id, Integer.toString(problemNode.line), convertToHTML(problemNode.message),
                                    convertToHTML(problemNode.sourceCodeBefore), convertToHTML(problemNode.sourceCode),
                                    convertToHTML(problemNode.sourceCodeAfter),
                                    getUnderLine(problemNode.sourceCodeBefore, problemNode.sourceCodeAfter),
                                    Integer.toString(problemNode.charStart), Integer.toString(problemNode.charEnd), }));
                    globalErrorNumber++;
                }
                writer.write(messages.getString("discouraged_warnings.footer")); //$NON-NLS-1$
            }

            writer.write(messages.getString("footer")); //$NON-NLS-1$
            writer.flush();
            writer.close();
        }
        catch (final IOException e) {
            e.printStackTrace();
        }
    }

    private String extractPluginName(final String fileName) {
        // fileName is fully qualified and we want to extract the segment before
        // the log file name
        // file name contains only '/'
        final String logName = fileName.replace('\\', '/');
        final int index = logName.lastIndexOf('/');
        if (index == -1) {
            return null;
        }
        final int index2 = logName.lastIndexOf('/', index - 1);
        if (index2 == -1) {
            return null;
        }
        return logName.substring(index2 + 1, index);
    }

    private String extractRelativePath(final String sourceFileName, final String pluginName) {
        if (pluginName == null) {
            return sourceFileName;
        }
        final int index = pluginName.indexOf('_');
        if (index == -1) {
            return sourceFileName;
        }
        final String pluginShortName = pluginName.substring(0, index);
        final int index2 = sourceFileName.indexOf(pluginShortName);
        if (index2 == -1) {
            return sourceFileName;
        }
        return sourceFileName.substring(index2 + pluginShortName.length(), sourceFileName.length());
    }

    private String extractXmlFileName(final String fileName) {
        // fileName is fully qualified and we want to extract the segment before
        // the log file name
        // file name contains only '/'
        final String logName = fileName.replace('\\', '/');
        final int index = logName.lastIndexOf('/');
        if (index == -1) {
            return null;
        }
        return logName.substring(index + 1, logName.length());
    }
}
