package com.pmease.quickbuild.plugin.builder.ant.backport;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.DateUtils;
import org.apache.tools.ant.util.StringUtils;

public class AntLogger implements BuildLogger {
    public static final int LEFT_COLUMN_SIZE = 12;

    protected PrintStream output;

    protected int msgOutputLevel = Project.MSG_ERR;

    private long startTime = System.currentTimeMillis();

    public void setMessageOutputLevel(int level) {
        this.msgOutputLevel = level;
    }

    public void setOutputPrintStream(PrintStream output) {
        this.output = new PrintStream(output, true);
    }

    public void setErrorPrintStream(PrintStream err) {
    }

    public void setEmacsMode(boolean emacsMode) {
    }

    public void buildStarted(BuildEvent event) {
        startTime = System.currentTimeMillis();
    }

    public void buildFinished(BuildEvent event) {
        Throwable error = event.getException();
        StringBuffer message = new StringBuffer();
        if (error == null) {
            message.append("BUILD SUCCESSFUL\n");
        } else {
            message.append("BUILD FAILED");

            while (error instanceof BuildException) {
                Throwable cause = ((BuildException) error).getCause();
                if (cause != null && cause.toString().equals(error.getMessage())) {
                    error = cause;
                } else {
                    break;
                }
            }

            String errorMessage;
            if (Project.MSG_VERBOSE <= msgOutputLevel
            		|| !(error instanceof BuildException)) {
                errorMessage = StringUtils.getStackTrace(error);
            } else {
                errorMessage = error.toString();
            }
            BufferedReader reader = new BufferedReader(new StringReader(errorMessage.toString()));
            String line;
            try {
				while ((line = reader.readLine()) != null)
					message.append("\n ").append(line);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
            
        }
        message.append("\nTotal time: ");
        message.append(DateUtils.formatElapsedTime(System.currentTimeMillis() - startTime));

        String msg = message.toString();
        if (error == null)
            printMessage(msg, -1);
        else
            printMessage(msg, Project.MSG_ERR);
    }
    
    private void printMessage(String msg, int priority) {
    	if (priority == Project.MSG_DEBUG)
    		output.println("TRACE " + msg);
    	else if (priority == Project.MSG_ERR)
    		output.println("ERROR " + msg);
    	else if (priority == Project.MSG_INFO)
    		output.println("INFO " + msg);
    	else if (priority == Project.MSG_VERBOSE)
    		output.println("DEBUG " + msg);
    	else if (priority == Project.MSG_WARN)
    		output.println("WARN " + msg);
    	else
    		output.println(msg);
    }
    
    public void targetStarted(BuildEvent event) {
        if (!event.getTarget().getName().equals(""))
            printMessage(event.getTarget().getName() + ":", Project.MSG_INFO);
    }

    public void targetFinished(BuildEvent event) {
    }

    public void taskStarted(BuildEvent event) {
    }

    public void taskFinished(BuildEvent event) {
    }

    public void messageLogged(BuildEvent event) {
        int priority = event.getPriority();
        if (priority <= Project.MSG_INFO || priority <= msgOutputLevel) {
            StringBuffer message = new StringBuffer();
            if (event.getTask() != null) {
                String name = event.getTask().getTaskName();
                String label = "[" + name + "] ";
                int size = LEFT_COLUMN_SIZE - label.length();
                StringBuffer tmp = new StringBuffer();
                for (int i = 0; i < size; i++)
                    tmp.append(" ");
                tmp.append(label);
                label = tmp.toString();

                BufferedReader reader = new BufferedReader(new StringReader(event.getMessage()));
                String line;
                try {
					while ((line = reader.readLine()) != null) {
						if (message.length() != 0)
							message.append("\n ").append(label).append(line);
						else
							message.append(label).append(line);
					}
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
            } else {
            	message.append(event.getMessage());
            }
            Throwable ex = event.getException();
            if (Project.MSG_DEBUG <= msgOutputLevel && ex != null)
            	message.append(StringUtils.getStackTrace(ex));

            if (event.getTask() != null) 
            	printMessage(event.getTask().getTaskName(), message.toString(), priority);
            else
            	printMessage(message.toString(), priority);
        }
    }

    private void printMessage(String taskName, String msg, int priority) {
    	if (taskName.equals("javac")) {
    		if (priority <= Project.MSG_WARN)
    			printMessage(msg, Project.MSG_WARN);
    		else
    			printMessage(msg, priority);
    	} else if (taskName.equals("groovyc")) {
    		if (msg.contains("MultipleCompilationErrorsException"))
    			printMessage(msg, Project.MSG_ERR);
    		else
    			printMessage(msg, priority);
    	} else if (taskName.equals("echo")) {
    		printMessage(msg, Project.MSG_INFO);
    	} else {
    		printMessage(msg, priority);
    	}
    }
}
