/*******************************************************************************
 * Copyright (c) 2008 IBM Corporation.
 * 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.ptp.rm.mpi.openmpi.core.rtsystem;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.osgi.util.NLS;
import org.eclipse.ptp.core.attributes.IllegalValueException;
import org.eclipse.ptp.core.elements.attributes.ProcessAttributes;
import org.eclipse.ptp.rm.mpi.openmpi.core.OpenMPIApplicationAttributes;
import org.eclipse.ptp.rm.mpi.openmpi.core.OpenMPIJobAttributes;
import org.eclipse.ptp.rm.mpi.openmpi.core.OpenMPINodeAttributes;
import org.eclipse.ptp.rm.mpi.openmpi.core.OpenMPIJobAttributes.MappingMode;
import org.eclipse.ptp.rm.mpi.openmpi.core.messages.Messages;

/**
 * 
 * @author Daniel Felix Ferber
 *
 */
public class OpenMPIProcessMapText12Parser {
	private OpenMPIProcessMapText12Parser() {
		// Do not allow instances.
	}

	OpenMPIProcessMap map = new OpenMPIProcessMap();
	int numApplications;
	int numNodes;

	public static OpenMPIProcessMap parse(InputStream is) throws IOException {
		OpenMPIProcessMapText12Parser parser = new OpenMPIProcessMapText12Parser();
		BufferedReader reader = new BufferedReader(new InputStreamReader(is), 1);

		parser.readStart(reader);
		parser.readVpid(reader);
		for (int i = 0; i < parser.numApplications; i++) {
			parser.readAppContext(reader);
		}
		parser.readNumElements(reader);
		for (int i = 0; i < parser.numNodes; i++) {
			parser.readMappedNode(reader, i);
		}

		return parser.map;
	}

	/*
	 * Find mapped node information, ignoring anything else. Format should be:
	 * 
	 * 		Mapped node:
	 * 			Cell: 0 Nodename: dyn531995.br.ibm.com Launch id: -1 Username: NULL
	 * 			Daemon name:
	 * 				Data type: ORTE_PROCESS_NAME Data Value: NULL
	 * 			Oversubscribed: True Num elements in procs list: 6
	 * 			Mapped proc:
	 * 				Proc Name:
	 * 				Data type: ORTE_PROCESS_NAME Data Value: [0,1,0]
	 * 				Proc Rank: 0 Proc PID: 0 App_context index: 0
	 */
	private void readMappedNode(BufferedReader reader, int nodeCounter) throws IOException {
		Pattern p = Pattern.compile("\\s*Mapped node:"); //$NON-NLS-1$
		String line;
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				break;
			}
		}
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}

		p = Pattern.compile("\\s*Cell:\\s*(\\S*)\\s*Nodename:\\s*(\\S*)\\s*Launch id:\\s*(\\S*)\\s*Username:\\s*(\\S*)"); //$NON-NLS-1$
		String nodeName = ""; //$NON-NLS-1$
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					nodeName = m.group(2);
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
		
		OpenMPIProcessMap.Node node = new OpenMPIProcessMap.Node(nodeName);
		map.addNode(node);

		p = Pattern.compile("\\s*Daemon name:"); //$NON-NLS-1$
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				break;
			}
		}
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
		
		p = Pattern.compile("\\s*Data type:\\s*\\S*\\s*Data Value:\\s*\\S*"); //$NON-NLS-1$
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				break;
			}
		}
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
		
		p = Pattern.compile("\\s*Oversubscribed:\\s*(\\S*)\\s*Num elements in procs list:\\s*(\\d*)"); //$NON-NLS-1$
		
		int numProcesses = 0;
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					String s = m.group(1);
					if (s.equalsIgnoreCase("true")) { //$NON-NLS-1$
						node.getAttributeManager().addAttribute(OpenMPINodeAttributes.getOversubscribedAttributeDefinition().create(true));
					} else if (s.equalsIgnoreCase("false")) { //$NON-NLS-1$
						node.getAttributeManager().addAttribute(OpenMPINodeAttributes.getOversubscribedAttributeDefinition().create(false));
					} else {
						throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
					}
					s = m.group(2);
					numProcesses = Integer.parseInt(s);
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}

		p = Pattern.compile("\\s*Mapped proc:"); //$NON-NLS-1$
		Pattern p2 = Pattern.compile("\\s*Proc Name:\\s*(\\S*)"); //$NON-NLS-1$
		Pattern p3 = Pattern.compile("\\s*Data type:\\s*\\S*\\s*Data Value:\\s*\\S*"); //$NON-NLS-1$
		Pattern p4 = Pattern.compile("\\s*Proc Rank:\\s*(\\d*)\\s*Proc PID:\\s*(\\d*)\\s*App_context index:\\s*(\\d*)"); //$NON-NLS-1$

		for (int i = 0; i < numProcesses; i ++) {
			String processName = ""; //$NON-NLS-1$
			int processIndex = 0;
			int processPid = 0;
			int applicationIndex = 0;

			// Mapped proc:
			while ((line = reader.readLine()) != null) {
				Matcher m = p.matcher(line);
				if (m.matches()) {
					break;
				}
			}
			if (line == null) {
				throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
			}
			
			// Proc Name:
			while ((line = reader.readLine()) != null) {
				Matcher m = p2.matcher(line);
				if (m.matches()) {
					processName = m.group(1);
					break;
				}
			}
			if (line == null) {
				throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
			}

			// Data type:
			while ((line = reader.readLine()) != null) {
				Matcher m = p3.matcher(line);
				if (m.matches()) {
					break;
				}
			}
			if (line == null) {
				throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
			}
			
			// Proc Rank:
			while ((line = reader.readLine()) != null) {
				Matcher m = p4.matcher(line);
				if (m.matches()) {
					try {
						String s = m.group(1);
						processIndex = Integer.parseInt(s);
						s = m.group(2);
						processPid = Integer.parseInt(s);
						s = m.group(3);
						applicationIndex = Integer.parseInt(s);
					} catch (NumberFormatException e) {
						throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
					}
					
					break;
				}
			}
			if (line == null) {
				throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
			}

			OpenMPIProcessMap.Process proc = new OpenMPIProcessMap.Process(node, processIndex, processName, applicationIndex);
			map.addProcess(proc);
			try {
				proc.getAttributeManager().addAttribute(ProcessAttributes.getPIDAttributeDefinition().create(processPid));
			} catch (IllegalValueException e) {
				// This is not possible.
				assert false;
			}
		}
	}

	/*
	 * Find num elements line, ignoring anything else. Format should be:
	 *
	 *		Num elements in nodes list: 1
	 */
	private void readNumElements(BufferedReader reader) throws IOException {
		Pattern p = Pattern.compile("\\s*Num elements in nodes list:\\s*(\\d*)"); //$NON-NLS-1$
		String line;
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					String s = m.group(1);
					numNodes = Integer.parseInt(s);
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
	}
	
	/*
	 * Find app context, ignoring anything else. Format should be:
	 * 
	 * 		Data for app_context: index 0 app: hello
	 * 			Num procs: 4
	 * 			Argv[0]: hello
	 * 			Env[0]: OMPI_MCA_rmaps_base_display_map=1
	 *			Env[1]: OMPI_MCA_orte_precondition_transports=e91ae2fd9a00796a-e5685cefcdbaa089
	 *			...
	 *			Working dir: /home/dfferber/EclipseWorkspaces/runtime-New_configuration/hello/Debug (user: 0)
	 *			Num maps: 0
	 *			
	 */
	private void readAppContext(BufferedReader reader) throws IOException {
		String line;
		int applicationIndex = 0;
		String applicationName = ""; //$NON-NLS-1$
		int numberOfProcessors = 0;

		Pattern p = Pattern.compile("\\s*Data for app_context:\\s*\\w*\\s*(\\d*)[^:]*:\\s*(.*)"); //$NON-NLS-1$
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
	
			if (m.matches()) {
				try {
					String s = m.group(1);
					applicationIndex = Integer.parseInt(s);
					s = m.group(2);
					applicationName = s;
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
			}
			
			break;
		}
		
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
		
		p = Pattern.compile("\\s*Num procs:\\s*(\\d*)"); //$NON-NLS-1$
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					String s = m.group(1);
					numberOfProcessors = Integer.parseInt(s);
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}

		OpenMPIProcessMap.Application application = new OpenMPIProcessMap.Application(applicationIndex, applicationName, numberOfProcessors);
		map.addApplication(application);

		/*
		 * Collect Argv and Env lines until we match Working Dir
		 */
		Pattern p1 = Pattern.compile("\\s*Argv\\[\\d*\\]\\s*:\\s*(.*)"); //$NON-NLS-1$
		Pattern p2 = Pattern.compile("\\s*Env\\[\\d*\\]\\s*:\\s*(.*)"); //$NON-NLS-1$
		p = Pattern.compile("\\s*Working dir:\\s*(.*)"); //$NON-NLS-1$

		List<String> arguments = new ArrayList<String>();
		List<String> environment = new ArrayList<String>();

		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				String s = m.group(1).trim();
				application.getAttributeManager().addAttribute(OpenMPIApplicationAttributes.getEffectiveOpenMPIWorkingDirAttributeDefinition().create(s));
				break;
			}
			
			m = p1.matcher(line);
			if (m.matches()) {
				arguments.add(m.group(1));
			} else {
				m = p2.matcher(line);
				if (m.matches()) {
					environment.add(m.group(1));
				}
			}
		}
		
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
		
		application.getAttributeManager().addAttribute(OpenMPIApplicationAttributes.getEffectiveOpenMPIProgArgsAttributeDefinition().create(arguments.toArray(new String[arguments.size()])));
		application.getAttributeManager().addAttribute(OpenMPIApplicationAttributes.getEffectiveOpenMPIEnvAttributeDefinition().create(environment.toArray(new String[environment.size()])));

		int num_maps = 0;
		p = Pattern.compile("\\s*Num maps:\\s*(\\d*).*"); //$NON-NLS-1$
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					String s = m.group(1);
					num_maps = Integer.parseInt(s);
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
		
		/*
		 * Skip map information
		 */
		for (int i = 0; i < num_maps; i++) {
			line = reader.readLine();
		}
	}

	/*
	 * Find second line, ignoring anything else. Format should be:
	 * 
	 * 		Starting vpid: 0 Vpid range: 6 Num app_contexts: 2
	 */
	private void readVpid(BufferedReader reader) throws IOException {
		Pattern p = Pattern.compile("\\s*Starting vpid:\\s*(\\d*)\\s*Vpid range:\\s*(\\w*)\\s*Num app_contexts:\\s*(\\w*).*"); //$NON-NLS-1$
		String line;
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					String s = m.group(1);
					try {
						map.getAttributeManager().addAttribute(OpenMPIJobAttributes.getVpidStartAttributeDefinition().create(Integer.parseInt(s)));
					} catch (IllegalValueException e) {
						// This is not possible.
						assert false;
					}
					s = m.group(2);
					try {
						map.getAttributeManager().addAttribute(OpenMPIJobAttributes.getVpidRangeAttributeDefinition().create(Integer.parseInt(s)));
					} catch (IllegalValueException e) {
						// This is not possible.
						assert false;
					}
					s = m.group(3);
					numApplications = Integer.parseInt(s);
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		
		if (line == null) {		
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_BrokenDisplayMapInformation);
		}
	}
	
	/*
	 * Find start of map output. This is a line formatted like the one below. Ignore everything
	 * before this line.
	 * 
	 *		[dyn531995.br.ibm.com:12281] Map for job: 1 Generated by mapping mode: bynode
	 * 
	 */
	private void readStart(BufferedReader reader) throws IOException {
		Pattern p = Pattern.compile("\\[([^:]*):(\\d*)\\]\\s*Map for job:\\s*(\\d*)[^:]*:\\s*(\\w*).*"); //$NON-NLS-1$
		String line;
		
		while ((line = reader.readLine()) != null) {
			Matcher m = p.matcher(line);
			if (m.matches()) {
				try {
					map.getAttributeManager().addAttribute(OpenMPIJobAttributes.getHostnameAttributeDefinition().create(m.group(1)));
					try {
						map.getAttributeManager().addAttribute(OpenMPIJobAttributes.getMpiJobIdAttributeDefinition().create(Integer.parseInt(m.group(3))));
					} catch (IllegalValueException e) {
						// This is not possible.
						assert false;
					}
					String mode = m.group(4);
					if (mode.equalsIgnoreCase("bynode")) { //$NON-NLS-1$
						map.getAttributeManager().addAttribute(OpenMPIJobAttributes.getMappingModeAttributeDefinition().create(MappingMode.BY_NODE));
					} else if (mode.equalsIgnoreCase("byslot")) { //$NON-NLS-1$
						map.getAttributeManager().addAttribute(OpenMPIJobAttributes.getMappingModeAttributeDefinition().create(MappingMode.BY_SLOT));
					} else {
						throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
					}
				} catch (NumberFormatException e) {
					throw new IOException(NLS.bind(Messages.OpenMPIProcessMapText12Parser_Exception_InvalidLine, line));
				}
				
				break;
			}
		}
		
		if (line == null) {
			throw new IOException(Messages.OpenMPIProcessMapText12Parser_Exception_MissingDisplayMapInformation);
		}
	}
	
	public static void main(String[] args) {
		try {
			FileInputStream is = new FileInputStream("test.txt"); //$NON-NLS-1$
			OpenMPIProcessMapText12Parser.parse(is);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
