/*******************************************************************************
 * Copyright (c) 2003, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ant.internal.launching.remote.logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.util.StringUtils;
import org.eclipse.ant.internal.launching.debug.AntDebugState;
import org.eclipse.ant.internal.launching.remote.AntSecurityException;
import org.eclipse.ant.internal.launching.remote.IAntCoreConstants;
import org.eclipse.ant.internal.launching.remote.InternalAntRunner;
import org.eclipse.ant.internal.launching.remote.RemoteAntMessages;

/**
 * Parts adapted from org.eclipse.jdt.internal.junit.runner.RemoteTestRunner A build logger that reports via a socket connection. See MessageIds for
 * more information about the protocol.
 */
public class RemoteAntBuildLogger extends DefaultLogger {

	/** Time of the start of the build */
	private long fStartTime = System.currentTimeMillis();

	/**
	 * The client socket.
	 */
	private Socket fEventSocket;
	/**
	 * Print writer for sending messages
	 */
	private PrintWriter fWriter;
	/**
	 * Host to connect to, default is the localhost
	 */
	protected String fHost = IAntCoreConstants.EMPTY_STRING;
	/**
	 * Port to connect to.
	 */
	private int fEventPort = -1;

	private String fProcessId = null;

	/**
	 * Is the debug mode enabled?
	 */
	protected boolean fDebugMode = false;

	protected boolean fSentProcessId = false;

	private List<BuildEvent> fEventQueue;

	private String fLastFileName = null;
	private String fLastTaskName = null;

	@Override
	protected void printMessage(String message, PrintStream stream, int priority) {
		marshalMessage(priority, message);
	}

	/**
	 * Connect to the remote Ant build listener.
	 */
	protected void connect() {
		if (fDebugMode) {
			System.out.println("RemoteAntBuildLogger: trying to connect" + fHost + ":" + fEventPort); //$NON-NLS-1$ //$NON-NLS-2$
		}

		for (int i = 1; i < 5; i++) {
			try {
				fEventSocket = new Socket(fHost, fEventPort);
				fWriter = new PrintWriter(fEventSocket.getOutputStream(), true);
				return;
			}
			catch (IOException e) {
				// do nothing
			}
			try {
				Thread.sleep(500);
			}
			catch (InterruptedException e) {
				// do nothing
			}
		}
		shutDown();
	}

	/**
	 * Shutdown the connection to the remote build listener.
	 */
	protected void shutDown() {
		if (fEventQueue != null) {
			fEventQueue.clear();
		}
		if (fWriter != null) {
			fWriter.close();
			fWriter = null;
		}

		try {
			if (fEventSocket != null) {
				fEventSocket.close();
				fEventSocket = null;
			}
		}
		catch (IOException e) {
			// do nothing
		}
	}

	private void sendMessage(String msg) {
		if (fWriter == null) {
			return;
		}

		fWriter.println(msg);
	}

	@Override
	public void buildFinished(BuildEvent event) {
		if (!fSentProcessId) {
			establishConnection();
		}
		handleException(event);
		printMessage(getTimeString(System.currentTimeMillis() - fStartTime), out, Project.MSG_INFO);
		shutDown();
	}

	protected void handleException(BuildEvent event) {
		Throwable exception = event.getException();
		if (exception == null || exception instanceof AntSecurityException) {
			return;
		}

		StringBuilder message = new StringBuilder();
		message.append(System.lineSeparator());
		message.append(RemoteAntMessages.getString("RemoteAntBuildLogger.1")); //$NON-NLS-1$
		message.append(System.lineSeparator());
		if (Project.MSG_VERBOSE <= this.msgOutputLevel || !(exception instanceof BuildException)) {
			message.append(StringUtils.getStackTrace(exception));
		} else {
			if (exception instanceof BuildException) {
				message.append(exception.toString()).append(System.lineSeparator());
			} else {
				message.append(exception.getMessage()).append(System.lineSeparator());
			}
		}
		message.append(System.lineSeparator());
		printMessage(message.toString(), out, Project.MSG_ERR);
	}

	private String getTimeString(long milliseconds) {
		long seconds = milliseconds / 1000;
		long minutes = seconds / 60;
		seconds = seconds % 60;

		StringBuilder result = new StringBuilder(RemoteAntMessages.getString("RemoteAntBuildLogger.Total_time")); //$NON-NLS-1$
		if (minutes > 0) {
			result.append(minutes);
			if (minutes > 1) {
				result.append(RemoteAntMessages.getString("RemoteAntBuildLogger._minutes_2")); //$NON-NLS-1$
			} else {
				result.append(RemoteAntMessages.getString("RemoteAntBuildLogger._minute_3")); //$NON-NLS-1$
			}
		}
		if (seconds > 0) {
			if (minutes > 0) {
				result.append(' ');
			}
			result.append(seconds);

			if (seconds > 1) {
				result.append(RemoteAntMessages.getString("RemoteAntBuildLogger._seconds_4")); //$NON-NLS-1$
			} else {
				result.append(RemoteAntMessages.getString("RemoteAntBuildLogger._second_5")); //$NON-NLS-1$
			}
		}
		if (seconds == 0 && minutes == 0) {
			result.append(milliseconds);
			result.append(RemoteAntMessages.getString("RemoteAntBuildLogger._milliseconds_6")); //$NON-NLS-1$
		}
		return result.toString();
	}

	@Override
	public void targetStarted(BuildEvent event) {
		if (!fSentProcessId) {
			establishConnection();
		}

		if (Project.MSG_INFO <= msgOutputLevel) {
			marshalTargetMessage(event);
		}
	}

	protected void establishConnection() {
		if (fEventPort != -1) {
			connect();
		} else {
			shutDown();
			return;
		}

		fSentProcessId = true;
		StringBuilder message = new StringBuilder(MessageIds.PROCESS_ID);
		message.append(fProcessId);
		sendMessage(message.toString());
		if (fEventQueue != null) {
			for (BuildEvent buildEvent : fEventQueue) {
				processEvent(buildEvent);
			}
			fEventQueue = null;
		}
	}

	@SuppressWarnings("unused")
	@Override
	public void messageLogged(BuildEvent event) {
		if (event.getPriority() > msgOutputLevel && event.getPriority() != InternalAntRunner.MSG_PROJECT_HELP) {
			return;
		}

		if (!fSentProcessId) {
			if (event.getPriority() == InternalAntRunner.MSG_PROJECT_HELP) {
				if (Project.MSG_INFO > msgOutputLevel) {
					return;
				}
				// no buildstarted or project started for project help option
				establishConnection();
				return;
			}
			if (fEventQueue == null) {
				fEventQueue = new ArrayList<BuildEvent>(10);
			}
			fEventQueue.add(event);
			return;
		}

		processEvent(event);
	}

	private void processEvent(BuildEvent event) {
		if (event.getTask() != null && !emacsMode) {
			try {
				marshalTaskMessage(event);
			}
			catch (IOException e) {
				// do nothing
			}
		} else {
			marshalMessage(event);
		}
	}

	private void marshalMessage(BuildEvent event) {
		String eventMessage = event.getMessage();
		if (eventMessage.length() == 0) {
			return;
		}
		marshalMessage(event.getPriority(), eventMessage);
	}

	protected void marshalMessage(int priority, String message) {
		try {
			BufferedReader r = new BufferedReader(new StringReader(message));
			String line = r.readLine();
			StringBuffer messageLine;
			while (line != null) {
				messageLine = new StringBuffer();
				if (priority != -1) {
					messageLine.append(priority);
					messageLine.append(',');
				}
				messageLine.append(line);
				sendMessage(messageLine.toString());
				line = r.readLine();
			}
		}
		catch (IOException e) {
			// do nothing
		}
	}

	private void marshalTaskMessage(BuildEvent event) throws IOException {
		String eventMessage = event.getMessage();
		if (eventMessage.length() == 0) {
			return;
		}
		BufferedReader r = new BufferedReader(new StringReader(eventMessage));
		String line = r.readLine();
		StringBuffer message;
		String taskName = event.getTask().getTaskName();
		if (taskName != null && taskName.equals(fLastTaskName)) {
			taskName = IAntCoreConstants.EMPTY_STRING;
		} else {
			fLastTaskName = taskName;
		}
		Location location = event.getTask().getLocation();
		String fileName = null;
		int lineNumber = -1;
		try {
			fileName = location.getFileName();
			lineNumber = location.getLineNumber();
		}
		catch (NoSuchMethodError e) {
			// older Ant
			fileName = location.toString();
		}
		if (location.equals(Location.UNKNOWN_LOCATION)) {
			fileName = location.toString();
			lineNumber = -1;
		}
		int priority = event.getPriority();
		while (line != null) {
			message = new StringBuffer(MessageIds.TASK);
			message.append(priority);
			message.append(',');
			message.append(taskName);
			message.append(',');
			message.append(line.length());
			message.append(',');
			message.append(line);
			message.append(',');
			if (!fileName.equals(fLastFileName)) {
				message.append(fileName.length());
				message.append(',');
				message.append(fileName);
			}
			message.append(',');
			message.append(lineNumber);
			sendMessage(message.toString());
			fLastFileName = fileName;
			line = r.readLine();
		}
	}

	private void marshalTargetMessage(BuildEvent event) {
		Target target = event.getTarget();
		Location location = AntDebugState.getLocation(target);

		StringBuilder message = new StringBuilder();
		message.append(MessageIds.TARGET);
		message.append(',');
		message.append(target.getName());
		message.append(':');
		message.append(',');
		if (location != null && location != Location.UNKNOWN_LOCATION) {
			// if a target has a valid location then we are on an Ant that is
			// new enough to have the accessor methods on Location
			String fileName = location.getFileName();
			message.append(fileName.length());
			message.append(',');
			message.append(fileName);
			message.append(',');
			message.append(location.getLineNumber());
		}
		sendMessage(message.toString());
	}

	@Override
	public void buildStarted(BuildEvent event) {
		establishConnection();
		super.buildStarted(event);
	}

	public void configure(Map<String, String> userProperties) {
		String portProperty = userProperties.remove("eclipse.connect.port"); //$NON-NLS-1$

		if (portProperty != null) {
			fEventPort = Integer.parseInt(portProperty);
		}

		fProcessId = userProperties.remove("org.eclipse.ant.core.ANT_PROCESS_ID"); //$NON-NLS-1$
	}
}