/*
 *(c) Copyright QNX Software Systems Ltd. 2002.
 * All Rights Reserved.
 * 
 */

package org.eclipse.cdt.debug.internal.core;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;

import org.eclipse.cdt.debug.core.*;
import org.eclipse.cdt.debug.core.cdi.model.ICDIInstruction;
import org.eclipse.cdt.debug.core.model.IExecFileInfo;
import org.eclipse.cdt.debug.core.sourcelookup.IDisassemblyStorage;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IDebugTarget;

/**
 * Enter type comment.
 * 
 * @since: Oct 8, 2002
 */
public class DisassemblyStorage implements IDisassemblyStorage
{
	protected ICDIInstruction[] fInstructions;
	protected IDebugTarget fDebugTarget;
	protected ByteArrayInputStream fInputStream = null;
	protected long fStartAddress = 0;
	protected long fEndAddress = 0;
	
	/**
	 * Constructor for DisassemblyStorage.
	 */
	public DisassemblyStorage( IDebugTarget target, ICDIInstruction[] instructions )
	{
		setDebugTarget( target );
		setInstructions( instructions );
		initializeAddresses();
		createContent();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.core.IDisassemblyStorage#getDebugTarget()
	 */
	public IDebugTarget getDebugTarget()
	{
		return fDebugTarget;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.core.IDisassemblyStorage#containsAddress(Long)
	 */
	public boolean containsAddress( long address )
	{
		return ( address >= fStartAddress && address <= fEndAddress );
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.core.IDisassemblyStorage#getLineNumber(Long)
	 */
	public int getLineNumber( long address )
	{
		for ( int i = 0; i < fInstructions.length; ++i )
		{
			if ( fInstructions[i].getAdress() == address )
			{
				return i + 1;
			}
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.resources.IStorage#getContents()
	 */
	public InputStream getContents() throws CoreException
	{
		if ( fInputStream != null )
			fInputStream.reset();
		return fInputStream;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.resources.IStorage#getFullPath()
	 */
	public IPath getFullPath()
	{
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.resources.IStorage#getName()
	 */
	public String getName()
	{
		try
		{
			if ( getDebugTarget() != null )
			{ 
				return  getDebugTarget().getName();
			}
		}
		catch( DebugException e )
		{
			// ignore
		}
		return "disassembly";
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.resources.IStorage#isReadOnly()
	 */
	public boolean isReadOnly()
	{
		return true;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
	 */
	public Object getAdapter( Class adapter )
	{
		if ( adapter.equals( IStorage.class ) )
			return this;
		if ( adapter.equals( IDisassemblyStorage.class ) )
			return this;
		if ( adapter.equals( DisassemblyStorage.class ) )
			return this;
		if ( adapter.equals( IResource.class ) )
			return getBinary();
		return null;
	}

	protected void setDebugTarget( IDebugTarget target )
	{
		fDebugTarget = target;
	}
	
	protected void setInstructions( ICDIInstruction[] intructions )
	{
		fInstructions = intructions;
	}

	private void createContent()
	{
		StringBuffer lines = new StringBuffer();
		int maxFunctionName = 0;
		int maxOpcodeLength = 0;
		long maxOffset = 0;
		for ( int i = 0; i < fInstructions.length; ++i )
		{
			if ( fInstructions[i].getFuntionName().length() > maxFunctionName )
			{
				maxFunctionName = fInstructions[i].getFuntionName().length();
			}

			String opcode = fInstructions[i].getOpcode();
			if ( opcode.length() > maxOpcodeLength )
				maxOpcodeLength = opcode.length();

			if ( fInstructions[i].getOffset() > maxOffset )
			{
				maxOffset = fInstructions[i].getOffset();
			}
		}
		int instrPos = calculateInstructionPosition( maxFunctionName, maxOffset );		
		int argPosition = instrPos + maxOpcodeLength + 1;
		for ( int i = 0; i < fInstructions.length; ++i )
		{
			lines.append( getInstructionString( fInstructions[i], instrPos, argPosition ) );
		}
		fInputStream = new ByteArrayInputStream( lines.toString().getBytes() );
	}

	private void initializeAddresses()
	{
		if ( fInstructions.length > 0 )
		{
			fStartAddress = fInstructions[0].getAdress();
			fEndAddress = fInstructions[fInstructions.length - 1].getAdress();
		}
	}
	
	private String getInstructionString( ICDIInstruction instruction, int instrPosition, int argPosition )
	{
		int worstCaseSpace = Math.max( instrPosition, argPosition );
		char[] spaces= new char[worstCaseSpace];
		Arrays.fill( spaces, ' ' );
		StringBuffer sb = new StringBuffer();
		if ( instruction != null )
		{
			sb.append( CDebugUtils.toHexAddressString( instruction.getAdress() ) );
			sb.append( ' ' );
			if ( instruction.getFuntionName() != null && instruction.getFuntionName().length() > 0 )
			{
				sb.append( '<' );
				sb.append( instruction.getFuntionName() );
				if ( instruction.getOffset() != 0 )
				{
					sb.append( '+' );
					sb.append( instruction.getOffset() );
				}
				sb.append( ">:" );
				sb.append( spaces, 0, instrPosition - sb.length() );
			}
			sb.append( instruction.getOpcode() );
			sb.append( spaces, 0, argPosition - sb.length() );
			sb.append( instruction.getArgs() );
			sb.append( '\n' );
		}
		return sb.toString();
	}
	
	private int calculateInstructionPosition( int maxFunctionName, long maxOffset )
	{
		return ( 16 + maxFunctionName + Long.toString( maxOffset ).length() );
	}
	
	private IResource getBinary()
	{
		if ( getDebugTarget() != null )
		{
			IExecFileInfo info = (IExecFileInfo)getDebugTarget().getAdapter( IExecFileInfo.class );
			if ( info != null )
			{
				return info.getExecFile();
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.core.sourcelookup.IDisassemblyStorage#getAddress(int)
	 */
	public long getAddress( int lineNumber )
	{
		if ( fInstructions.length > lineNumber && lineNumber >= 0 )
		{
			return fInstructions[lineNumber].getAdress();
		}
		return 0;
	}
}
