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

package org.eclipse.cdt.debug.internal.ui.views.memory;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.cdt.debug.core.CDebugUtils;
import org.eclipse.cdt.debug.core.ICMemoryManager;
import org.eclipse.cdt.debug.core.model.IFormattedMemoryBlock;
import org.eclipse.cdt.debug.core.model.IFormattedMemoryBlockRow;
import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils;
import org.eclipse.debug.core.DebugException;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;

/**
 * 
 * Provides rendering methods to the MemoryText widget.
 * 
 * @since Jul 25, 2002
 */
public class MemoryPresentation
{
	private static final int INTERVAL_BETWEEN_ADDRESS_AND_DATA = 2;
	private static final int INTERVAL_BETWEEN_DATA_ITEMS = 1;
	private static final int INTERVAL_BETWEEN_DATA_AND_ASCII = 1;
	
	private IFormattedMemoryBlock fBlock;
	
	private List fAddressZones;
	private List fChangedZones;

	private boolean fDisplayAscii = true;

	/**
	 * Constructor for MemoryPresentation.
	 */
	public MemoryPresentation()
	{		
		fAddressZones = new LinkedList();
		fChangedZones = new LinkedList();
	}

	public IFormattedMemoryBlock getMemoryBlock()
	{
		return fBlock;
	}

	public void setMemoryBlock( IFormattedMemoryBlock block )
	{
		fBlock = block;
	}
	
	/**
	 * Returns the string that contains the textual representation of 
	 * the memory according to this presentation.
	 * 
	 * @return the string that contains the textual representation of the memory
	 */
	public String getText()
	{
		fAddressZones.clear();
		IFormattedMemoryBlockRow[] rows = ( getMemoryBlock() != null ) ? getMemoryBlock().getRows() : new IFormattedMemoryBlockRow[0];
		StringBuffer sb = new StringBuffer();
		for ( int i = 0; i < rows.length; ++i )
		{
			int offset = sb.length();
			sb.append( getRowText( rows[i] ) );
			fAddressZones.add( new Point( offset, offset + getAddressLength() ) );
		}
		return sb.toString();
	}

	public String[] getText( Point[] zones )
	{
		return new String[0];
	}
	
	public boolean isAcceptable( char ch, int offset )
	{
		if ( isInAsciiArea( offset ) )
			return true;
		if ( isInDataArea( offset ) )
			return isValidValue( ch );
		return false;
	}
	
	public Point[] getAddressZones()
	{
		return (Point[])fAddressZones.toArray( new Point[fAddressZones.size()] );
	}
	
	public Point[] getChangedZones()
	{
		fChangedZones.clear();
		Long[] changedAddresses = getChangedAddresses();
		for ( int i = 0; i < changedAddresses.length; ++i )
		{
			int dataOffset = getDataItemOffsetByAddress( changedAddresses[i] );
			if ( dataOffset != -1 )
			{
				fChangedZones.add( new Point( dataOffset, dataOffset + getDataItemLength() - 1 ) );
			}
			if ( displayASCII() )
			{
				int asciiOffset = getAsciiOffsetByAddress( changedAddresses[i] );
				if ( asciiOffset != -1 )
				{
					fChangedZones.add( new Point( asciiOffset, asciiOffset ) );
				}
			}			
		}
		return (Point[])fChangedZones.toArray( new Point[fChangedZones.size()] );
	}
	
	public String getStartAddress()
	{
		return ( fBlock != null ) ? getAddressString( fBlock.getStartAddress() ) : ""; 
	}

	public String getAddressExpression()
	{
		return ( fBlock != null ) ? fBlock.getAddressExpression() : "";
	}

	private String getInterval( int length )
	{
		char[] chars = new char[length];
		Arrays.fill( chars, ' ' );
		return new String( chars );
	}

	private String getAddressString( long address )
	{
		return CDebugUIUtils.toHexAddressString( address );
	}

	private String getRowText( IFormattedMemoryBlockRow row )
	{
		StringBuffer result = new StringBuffer( getRowLength() ); 
		result.append( getAddressString( row.getAddress() ) ); 
		result.append( getInterval( INTERVAL_BETWEEN_ADDRESS_AND_DATA ) );
		String[] items = row.getData();
		for ( int i = 0; i < items.length; ++i )
		{
			result.append( getDataItemPresentation( items[i] ) );
			result.append( getInterval( INTERVAL_BETWEEN_DATA_ITEMS ) );
		}
		if ( displayASCII() )
		{
			result.append( getInterval( INTERVAL_BETWEEN_DATA_AND_ASCII ) );
			result.append( row.getASCII() );
		}
		result.append( '\n' );
		return result.toString();
	}

	private int getRowLength()
	{
		return getAddressLength() + 
			   INTERVAL_BETWEEN_ADDRESS_AND_DATA +
			   (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) * getNumberOfDataItemsInRow() + 
			   ( ( displayASCII() ) ? INTERVAL_BETWEEN_DATA_AND_ASCII +
			   getDataBytesPerRow() : 0 ) + 1;
	}

	private int getAddressLength()
	{
		return 10;
	}
	
	private boolean isInAsciiArea( int offset )
	{
		if ( displayASCII() && getRowLength() != 0 )
		{
			int pos = offset % getRowLength();
			int asciiColumn = getAddressLength() + 
			   				  INTERVAL_BETWEEN_ADDRESS_AND_DATA +
			   				  (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS ) * getNumberOfDataItemsInRow() + 
			   				  INTERVAL_BETWEEN_DATA_AND_ASCII;
			return ( pos >=  asciiColumn && pos < getRowLength() - 1 ); 
		}
		return false;
	}

	private boolean isInDataArea( int offset )
	{
		if ( getRowLength() != 0 )
		{
			int pos = offset % getRowLength();
			int dataBegin = getAddressLength() + INTERVAL_BETWEEN_ADDRESS_AND_DATA;
			int dataEnd = dataBegin + ((getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS ) * getNumberOfDataItemsInRow());
			if ( pos >= dataBegin && pos < dataEnd )
				return isInDataItem( pos - dataBegin );
		}
		return false;
	}

	private boolean isInDataItem( int pos )
	{
		for ( int i = 0; i < getNumberOfDataItemsInRow(); ++i )
		{
			if ( pos < i * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) )
				return false;
			if ( pos >= i * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) &&
				 pos < (i * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS)) + getDataItemLength() )
				return true;
		}
		return false;
	}

	private int getDataItemLength()
	{
		if ( getMemoryBlock() != null )
		{
			switch( getDataFormat() )
			{
				case IFormattedMemoryBlock.MEMORY_FORMAT_HEX:
					return getMemoryBlock().getWordSize() * 2;
				case IFormattedMemoryBlock.MEMORY_FORMAT_SIGNED_DECIMAL:
					return getDecimalDataItemLength( getMemoryBlock().getWordSize(), true );
				case IFormattedMemoryBlock.MEMORY_FORMAT_UNSIGNED_DECIMAL:
					return getDecimalDataItemLength( getMemoryBlock().getWordSize(), false );
			}
		}
		return 0;
	}
	
	private int getNumberOfDataItemsInRow()
	{
		if ( getMemoryBlock() != null )
			return getMemoryBlock().getNumberOfColumns();
		return 0;
	}

	protected boolean displayASCII()
	{
		if ( canDisplayAscii() )
			return fDisplayAscii;
		return false;
	}
	
	protected void setDisplayAscii( boolean displayAscii )
	{
		fDisplayAscii = displayAscii;
	}
 
	private int getDataBytesPerRow()
	{
		if ( getMemoryBlock() != null )
			return getMemoryBlock().getNumberOfColumns() * getMemoryBlock().getWordSize();
		return 0;
	}

	private boolean isValidValue( char ch )
	{
		switch( getDataFormat() )
		{
			case ICMemoryManager.MEMORY_FORMAT_HEX:
				return isHexadecimal( ch );
			case ICMemoryManager.MEMORY_FORMAT_BINARY:
			case ICMemoryManager.MEMORY_FORMAT_OCTAL:
			case ICMemoryManager.MEMORY_FORMAT_SIGNED_DECIMAL:
			case ICMemoryManager.MEMORY_FORMAT_UNSIGNED_DECIMAL:
			case -1:
			default:
				return false;
		}
	}

	private boolean isHexadecimal( char ch )
	{
		return ( Character.isDigit( ch ) ||
				 ( ch >= 'a' && ch <= 'f' ) ||
				 ( ch >= 'A' && ch <= 'F' ) );
	}
	
	private int getDataFormat()
	{
		if ( getMemoryBlock() != null )
			return getMemoryBlock().getFormat();
		return IFormattedMemoryBlock.MEMORY_FORMAT_HEX;
	}
	
	private Long[] getChangedAddresses()
	{
		return ( getMemoryBlock() != null ) ? getMemoryBlock().getChangedAddresses() : new Long[0];
	}
	
	private int getDataItemOffsetByAddress( Long address )
	{
		if ( getMemoryBlock() != null )
		{
			IFormattedMemoryBlockRow[] rows = getMemoryBlock().getRows();
			for ( int i = 0; i < rows.length; ++i )
			{
				int wordSize = getMemoryBlock().getWordSize();
				int numberOfColumns = getMemoryBlock().getNumberOfColumns();
				if ( address.longValue() >= rows[i].getAddress() && 
					 address.longValue() < rows[i].getAddress() + (wordSize * numberOfColumns) )
				{
					for ( int j = 1; j <= numberOfColumns; ++j )
					{
						if ( address.longValue() >= rows[i].getAddress() + ((j - 1) * wordSize) &&
							 address.longValue() < rows[i].getAddress() + (j * wordSize) )
						{
							return (i * getRowLength()) + ((j - 1) * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS)) + getAddressLength() + INTERVAL_BETWEEN_ADDRESS_AND_DATA;
						}
					}
				}
			}
			
		}
		return -1;
	}
	
	private int getAsciiOffsetByAddress( Long address )
	{
		if ( getMemoryBlock() != null )
		{
			IFormattedMemoryBlockRow[] rows = getMemoryBlock().getRows();
			if ( rows.length > 0 )
			{
				IFormattedMemoryBlockRow firstRow = rows[0];
				IFormattedMemoryBlockRow lastRow = rows[rows.length - 1];
				if ( address.longValue() >= firstRow.getAddress() && address.longValue() <= lastRow.getAddress() )
				{
					int asciiOffset = (int)(address.longValue() - firstRow.getAddress());
					int asciiRowlength = getMemoryBlock().getWordSize() * getMemoryBlock().getNumberOfColumns();
					int numberOfRows = asciiOffset / asciiRowlength;
					int offsetInRow = asciiOffset % asciiRowlength;
					return (numberOfRows * getRowLength()) + 
						   getAddressLength() + INTERVAL_BETWEEN_ADDRESS_AND_DATA +
						   (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) * getMemoryBlock().getNumberOfColumns() +
						   INTERVAL_BETWEEN_DATA_AND_ASCII + offsetInRow;
				}
			}
		}
		return -1;
	}
	
	protected boolean canDisplayAscii()
	{
		if ( getMemoryBlock() != null )
			return getMemoryBlock().displayASCII();
		return false;
	}

	protected int getDataItemIndex( int offset )
	{
		int row = offset / getRowLength();
		int pos = offset % getRowLength() - getAddressLength() - INTERVAL_BETWEEN_ADDRESS_AND_DATA;
		for ( int i = 0; i < getNumberOfDataItemsInRow(); ++i )
		{
			if ( pos < i * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) )
				return -1;
			if ( pos >= i * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) &&
				 pos < (i * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS)) + getDataItemLength() )
				return i + (row * getNumberOfDataItemsInRow());
		}
		if ( displayASCII() && pos >= getNumberOfDataItemsInRow() * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) + INTERVAL_BETWEEN_DATA_AND_ASCII )
		{
			return ((pos - ((getNumberOfDataItemsInRow() * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS) + INTERVAL_BETWEEN_DATA_AND_ASCII))) * 2 / getDataItemLength()) + row * getNumberOfDataItemsInRow();
		}
		return -1;
	}

	private int getDataItemOffset( int index )
	{
		int row = index / getNumberOfDataItemsInRow();
		int pos = index % getNumberOfDataItemsInRow();
		return row * getRowLength() + 
			   getAddressLength() + INTERVAL_BETWEEN_ADDRESS_AND_DATA +
			   pos * (getDataItemLength() + INTERVAL_BETWEEN_DATA_ITEMS); 
	}

	private char[] getDataItemChars( int index )
	{
		if ( getMemoryBlock() != null )
		{
			int rowNumber = index / getMemoryBlock().getNumberOfColumns();
			int pos = index % getMemoryBlock().getNumberOfColumns();
			IFormattedMemoryBlockRow[] rows = getMemoryBlock().getRows();
			if ( rowNumber < rows.length )
			{
				String[] data = rows[rowNumber].getData();
				if ( pos < data.length )
				{
					return data[pos].toCharArray();
				}
			}
		}
		return new char[0];
	}
	
	private int getOffsetInDataItem( int offset, int index )
	{
		if ( isInDataArea( offset ) )
		{
			return offset - getDataItemOffset( index );
		}
		return -1;
	}

	public void dispose()
	{
		if ( fAddressZones != null )
		{
			fAddressZones.clear();
		}
		if ( fChangedZones != null )
		{
			fChangedZones.clear();
		}
	}

	private String getDataItemPresentation( String item )
	{
		switch( getDataFormat() )
		{
			case IFormattedMemoryBlock.MEMORY_FORMAT_HEX:
				return item;
			case IFormattedMemoryBlock.MEMORY_FORMAT_SIGNED_DECIMAL:
				return convertToDecimal( getWordSize(), item, true );
			case IFormattedMemoryBlock.MEMORY_FORMAT_UNSIGNED_DECIMAL:
				return convertToDecimal( getWordSize(), item, false );
		}
		return "";
	}
	
	private int getDecimalDataItemLength( int wordSize, boolean signed )
	{
		switch( wordSize )
		{
			case IFormattedMemoryBlock.MEMORY_SIZE_BYTE:
				return ( signed ) ? 4 : 3;
			case IFormattedMemoryBlock.MEMORY_SIZE_HALF_WORD:
				return ( signed ) ? 6 : 5;
			case IFormattedMemoryBlock.MEMORY_SIZE_WORD:
				return ( signed ) ? 11 : 10;
		}
		return 0;
	}
	
	private int getWordSize()
	{
		if ( getMemoryBlock() != null )
		{
			return getMemoryBlock().getWordSize();
		}
		return 0;
	}
	
	private String convertToDecimal( int wordSize, String item, boolean signed )
	{
		String result = "";
		boolean le = getMemoryBlock().isLittleEndian();
		switch( wordSize )
		{
			case IFormattedMemoryBlock.MEMORY_SIZE_BYTE:
				result = Long.toString( ( signed ) ? CDebugUtils.toByte( item.toCharArray(), le ) : CDebugUtils.toUnsignedByte( item.toCharArray(), le ) );
				break;
			case IFormattedMemoryBlock.MEMORY_SIZE_HALF_WORD:
				result = Long.toString( ( signed ) ? CDebugUtils.toShort( item.toCharArray(), le ) : CDebugUtils.toUnsignedShort( item.toCharArray(), le ) );
				break;
			case IFormattedMemoryBlock.MEMORY_SIZE_WORD:
				result = Long.toString( ( signed ) ? CDebugUtils.toInt( item.toCharArray(), le ) : CDebugUtils.toUnsignedInt( item.toCharArray(), le ) );
				break;
		}
		return CDebugUtils.prependString( result, getDataItemLength(), ' ' );
	}
	
	protected boolean isStartAddressChanged()
	{
		if ( getMemoryBlock() != null )
		{
			return getMemoryBlock().isStartAddressChanged();
		}
		return false;
	}
	
	protected String getNewItemValue( int offset, char newChar )
	{
		if ( getMemoryBlock() != null )
		{
			int index = getDataItemIndex( offset );
			if ( index != -1 )
			{
				char[] chars = getDataItemChars( index );
				if ( isInDataArea( offset ) )
				{
					int charIndex = getOffsetInDataItem( offset, index );
					chars[charIndex] = newChar;
				}
				if ( isInAsciiArea( offset ) )
				{
					chars = CDebugUtils.getByteText( (byte)newChar );
				}
				return new String( chars );
			}
		}
		return null;
	}

	protected void setItemValue( int offset, char ch )
	{
		if ( getMemoryBlock() != null )
		{
			int index = getDataItemIndex( offset );
			if ( index != -1 )
			{
				String newValue = getNewItemValue( offset, ch );
				if ( newValue != null )
				{
					try
					{
						getMemoryBlock().setItemValue( index, newValue );
						return;
					}
					catch( DebugException e )
					{
						Display.getDefault().beep();
					}
				}
			}
		}
		Display.getDefault().beep();
	}
}
