/*
 **********************************************************************
 *   Copyright (C) 1998-2009, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 */

#include "LETypes.h"
#include "LEInsertionList.h"
#include "LEGlyphStorage.h"

U_NAMESPACE_BEGIN

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LEGlyphStorage)

LEInsertionCallback::~LEInsertionCallback()
{
	// nothing to do...
}

LEGlyphStorage::LEGlyphStorage()
    : fGlyphCount(0), fGlyphs(NULL), fCharIndices(NULL), fPositions(NULL),
      fAuxData(NULL), fInsertionList(NULL), fSrcIndex(0), fDestIndex(0)
{
    // nothing else to do!
}

LEGlyphStorage::~LEGlyphStorage()
{
    reset();
}

void LEGlyphStorage::reset()
{
    fGlyphCount = 0;

    if (fPositions != NULL) {
        LE_DELETE_ARRAY(fPositions);
        fPositions = NULL;
    }

    if (fAuxData != NULL) {
        LE_DELETE_ARRAY(fAuxData);
        fAuxData = NULL;
    }

    if (fInsertionList != NULL) {
        delete fInsertionList;
        fInsertionList = NULL;
    }

    if (fCharIndices != NULL) {
        LE_DELETE_ARRAY(fCharIndices);
        fCharIndices = NULL;
    }

    if (fGlyphs != NULL) {
        LE_DELETE_ARRAY(fGlyphs);
        fGlyphs = NULL;
    }
}

// FIXME: This might get called more than once, for various reasons. Is
// testing for pre-existing glyph and charIndices arrays good enough?
void LEGlyphStorage::allocateGlyphArray(le_int32 initialGlyphCount, le_bool rightToLeft, LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return;
    }

    if (initialGlyphCount <= 0) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    if (fGlyphs == NULL) {
        fGlyphCount = initialGlyphCount;
        fGlyphs = LE_NEW_ARRAY(LEGlyphID, fGlyphCount);

        if (fGlyphs == NULL) {
            success = LE_MEMORY_ALLOCATION_ERROR;
            return;
        }
    }

    if (fCharIndices == NULL) {
        fCharIndices = LE_NEW_ARRAY(le_int32, fGlyphCount);

        if (fCharIndices == NULL) {
            LE_DELETE_ARRAY(fGlyphs);
            fGlyphs = NULL;
            success = LE_MEMORY_ALLOCATION_ERROR;
            return;
        }

        // Initialize the charIndices array
        le_int32 i, count = fGlyphCount, dir = 1, out = 0;

        if (rightToLeft) {
            out = fGlyphCount - 1;
            dir = -1;
        }

        for (i = 0; i < count; i += 1, out += dir) {
            fCharIndices[out] = i;
        }
    }

    if (fInsertionList == NULL) {
        // FIXME: check this for failure?
        fInsertionList = new LEInsertionList(rightToLeft);
        if (fInsertionList == NULL) { 
            LE_DELETE_ARRAY(fCharIndices);
            fCharIndices = NULL;

            LE_DELETE_ARRAY(fGlyphs);
            fGlyphs = NULL;

            success = LE_MEMORY_ALLOCATION_ERROR;
            return;
        }
    }
}

// FIXME: do we want to initialize the positions to [0, 0]?
le_int32 LEGlyphStorage::allocatePositions(LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return -1;
    }

    if (fPositions != NULL) {
        success = LE_INTERNAL_ERROR;
        return -1;
    }

    fPositions = LE_NEW_ARRAY(float, 2 * (fGlyphCount + 1));

    if (fPositions == NULL) {
        success = LE_MEMORY_ALLOCATION_ERROR;
        return -1;
    }

    return fGlyphCount;
}

// FIXME: do we want to initialize the aux data to NULL?
le_int32 LEGlyphStorage::allocateAuxData(LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return -1;
    }

    if (fAuxData != NULL) {
        success = LE_INTERNAL_ERROR;
        return -1;
    }

    fAuxData = LE_NEW_ARRAY(le_uint32, fGlyphCount);

    if (fAuxData == NULL) {
        success = LE_MEMORY_ALLOCATION_ERROR;
        return -1;
    }

    return fGlyphCount;
}

void LEGlyphStorage::getCharIndices(le_int32 charIndices[], le_int32 indexBase, LEErrorCode &success) const
{
    le_int32 i;

    if (LE_FAILURE(success)) {
        return;
    }

    if (charIndices == NULL) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    if (fCharIndices == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return;
    }

    for (i = 0; i < fGlyphCount; i += 1) {
        charIndices[i] = fCharIndices[i] + indexBase;
    }
}

void LEGlyphStorage::getCharIndices(le_int32 charIndices[], LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
      return;
    }
    
    if (charIndices == NULL) {
      success = LE_ILLEGAL_ARGUMENT_ERROR;
      return;
    }
    
    if (fCharIndices == NULL) {
      success = LE_NO_LAYOUT_ERROR;
      return;
    }
    
    LE_ARRAY_COPY(charIndices, fCharIndices, fGlyphCount);
}

// Copy the glyphs into caller's (32-bit) glyph array, OR in extraBits
void LEGlyphStorage::getGlyphs(le_uint32 glyphs[], le_uint32 extraBits, LEErrorCode &success) const
{
    le_int32 i;

    if (LE_FAILURE(success)) {
        return;
    }

    if (glyphs == NULL) {
        success = LE_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    if (fGlyphs == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return;
    }

    for (i = 0; i < fGlyphCount; i += 1) {
        glyphs[i] = fGlyphs[i] | extraBits;
    }
}

void LEGlyphStorage::getGlyphs(LEGlyphID glyphs[], LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
      return;
    }
    
    if (glyphs == NULL) {
      success = LE_ILLEGAL_ARGUMENT_ERROR;
      return;
    }
    
    if (fGlyphs == NULL) {
      success = LE_NO_LAYOUT_ERROR;
      return;
    }
    
    LE_ARRAY_COPY(glyphs, fGlyphs, fGlyphCount);
}

LEGlyphID LEGlyphStorage::getGlyphID(le_int32 glyphIndex, LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
        return 0xFFFF;
    }

    if (fGlyphs == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return 0xFFFF;
    }

    if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
        success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
        return 0xFFFF;
    }

    return fGlyphs[glyphIndex];
}

void LEGlyphStorage::setGlyphID(le_int32 glyphIndex, LEGlyphID glyphID, LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return;
    }

    if (fGlyphs == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return;
    }

    if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
        success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
        return;
    }

    fGlyphs[glyphIndex] = glyphID;
}

le_int32 LEGlyphStorage::getCharIndex(le_int32 glyphIndex, LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
        return -1;
    }

    if (fCharIndices == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return -1;
    }

    if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
        success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
        return -1;
    }

    return fCharIndices[glyphIndex];
}

void LEGlyphStorage::setCharIndex(le_int32 glyphIndex, le_int32 charIndex, LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return;
    }

    if (fCharIndices == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return;
    }

    if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
        success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
        return;
    }

    fCharIndices[glyphIndex] = charIndex;
}

void LEGlyphStorage::getAuxData(le_uint32 auxData[], LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
      return;
    }
    
    if (auxData == NULL) {
      success = LE_ILLEGAL_ARGUMENT_ERROR;
      return;
    }
    
    if (fAuxData == NULL) {
      success = LE_NO_LAYOUT_ERROR;
      return;
    }
    
    LE_ARRAY_COPY(auxData, fAuxData, fGlyphCount);
}

le_uint32 LEGlyphStorage::getAuxData(le_int32 glyphIndex, LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
        return 0;
    }

    if (fAuxData == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return 0;
    }
    
    if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
        success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
        return 0;
    }

    return fAuxData[glyphIndex];
}

void LEGlyphStorage::setAuxData(le_int32 glyphIndex, le_uint32 auxData, LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return;
    }

    if (fAuxData == NULL) {
        success = LE_NO_LAYOUT_ERROR;
        return;
    }

    if (glyphIndex < 0 || glyphIndex >= fGlyphCount) {
        success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
        return;
    }

    fAuxData[glyphIndex] = auxData;
}

void LEGlyphStorage::getGlyphPositions(float positions[], LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
      return;
    }
  
    if (positions == NULL) {
      success = LE_ILLEGAL_ARGUMENT_ERROR;
      return;
    }
    
    if (fPositions == NULL) {
      success = LE_NO_LAYOUT_ERROR;
      return;
    }
    
    LE_ARRAY_COPY(positions, fPositions, fGlyphCount * 2 + 2);
}

void LEGlyphStorage::getGlyphPosition(le_int32 glyphIndex, float &x, float &y, LEErrorCode &success) const
{
    if (LE_FAILURE(success)) {
      return;
    }
    
    if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
      success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
      return;
    }
    
    if (fPositions == NULL) {
      success = LE_NO_LAYOUT_ERROR;
      return;
    }
    
    x = fPositions[glyphIndex * 2];
    y = fPositions[glyphIndex * 2 + 1];
}

void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return;
    }
    
    if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
      success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
      return;
    }
    
    fPositions[glyphIndex * 2]     = x;
    fPositions[glyphIndex * 2 + 1] = y;
}

void LEGlyphStorage::adjustPosition(le_int32 glyphIndex, float xAdjust, float yAdjust, LEErrorCode &success)
{
    if (LE_FAILURE(success)) {
        return;
    }
    
    if (glyphIndex < 0 || glyphIndex > fGlyphCount) {
      success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
      return;
    }
    
    fPositions[glyphIndex * 2]     += xAdjust;
    fPositions[glyphIndex * 2 + 1] += yAdjust;
}

void LEGlyphStorage::adoptGlyphArray(LEGlyphStorage &from)
{
    if (fGlyphs != NULL) {
        LE_DELETE_ARRAY(fGlyphs);
    }

    fGlyphs = from.fGlyphs;
    from.fGlyphs = NULL;

    if (fInsertionList != NULL) {
        delete fInsertionList;
    }

    fInsertionList = from.fInsertionList;
    from.fInsertionList = NULL;
}

void LEGlyphStorage::adoptCharIndicesArray(LEGlyphStorage &from)
{
    if (fCharIndices != NULL) {
        LE_DELETE_ARRAY(fCharIndices);
    }

    fCharIndices = from.fCharIndices;
    from.fCharIndices = NULL;
}

void LEGlyphStorage::adoptPositionArray(LEGlyphStorage &from)
{
    if (fPositions != NULL) {
        LE_DELETE_ARRAY(fPositions);
    }

    fPositions = from.fPositions;
    from.fPositions = NULL;
}

void LEGlyphStorage::adoptAuxDataArray(LEGlyphStorage &from)
{
    if (fAuxData != NULL) {
        LE_DELETE_ARRAY(fAuxData);
    }

    fAuxData = from.fAuxData;
    from.fAuxData = NULL;
}

void LEGlyphStorage::adoptGlyphCount(LEGlyphStorage &from)
{
    fGlyphCount = from.fGlyphCount;
}

void LEGlyphStorage::adoptGlyphCount(le_int32 newGlyphCount)
{
    fGlyphCount = newGlyphCount;
}

// Move a glyph to a different position in the LEGlyphStorage ( used for Indic v2 processing )

void LEGlyphStorage::moveGlyph(le_int32 fromPosition, le_int32 toPosition, le_uint32 marker )
{

    LEErrorCode success = LE_NO_ERROR;

    LEGlyphID holdGlyph = getGlyphID(fromPosition,success);
    le_int32 holdCharIndex = getCharIndex(fromPosition,success);
    le_uint32 holdAuxData = getAuxData(fromPosition,success);

    if ( fromPosition < toPosition ) {
        for ( le_int32 i = fromPosition ; i < toPosition ; i++ ) {
            setGlyphID(i,getGlyphID(i+1,success),success);
            setCharIndex(i,getCharIndex(i+1,success),success);
            setAuxData(i,getAuxData(i+1,success),success);
        }
    } else {
        for ( le_int32 i = toPosition ; i > fromPosition ; i-- ) {
            setGlyphID(i,getGlyphID(i-1,success),success);
            setCharIndex(i,getCharIndex(i-1,success),success);
            setAuxData(i,getAuxData(i-1,success),success);

        }
    }

    setGlyphID(toPosition,holdGlyph,success);
    setCharIndex(toPosition,holdCharIndex,success);
    setAuxData(toPosition,holdAuxData | marker,success);

}

// Glue code for existing stable API
LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32  atIndex, le_int32 insertCount)
{
    LEErrorCode ignored = LE_NO_LAYOUT_ERROR;
    return insertGlyphs(atIndex, insertCount, ignored);
}

// FIXME: add error checking?
LEGlyphID *LEGlyphStorage::insertGlyphs(le_int32  atIndex, le_int32 insertCount, LEErrorCode& success)
{
    return fInsertionList->insert(atIndex, insertCount, success);
}

le_int32 LEGlyphStorage::applyInsertions()
{
    le_int32 growAmount = fInsertionList->getGrowAmount();

    if (growAmount == 0) {
        return fGlyphCount;
    }

    le_int32 newGlyphCount = fGlyphCount + growAmount;

    LEGlyphID *newGlyphs = (LEGlyphID *) LE_GROW_ARRAY(fGlyphs, newGlyphCount); 
    if (newGlyphs == NULL) { 
        // Could not grow the glyph array 
        return fGlyphCount; 
    } 

    le_int32 *newCharIndices = (le_int32 *) LE_GROW_ARRAY(fCharIndices, newGlyphCount);
    if (newCharIndices == NULL) { 
        // Could not grow the glyph array 
        return fGlyphCount; 
    } 

    if (fAuxData != NULL) {	
        le_uint32 *newAuxData = (le_uint32 *) LE_GROW_ARRAY(fAuxData, newGlyphCount); 
        if (newAuxData == NULL) { 
            // could not grow the aux data array 
            return fGlyphCount; 
        } 
        fAuxData = (le_uint32 *)newAuxData;
    }

	// Set grown arrays
    fGlyphs = newGlyphs; 
    fCharIndices = newCharIndices;

    fSrcIndex  = fGlyphCount - 1;
    fDestIndex = newGlyphCount - 1;

#if 0
    // If the current position is at the end of the array
    // update it to point to the end of the new array. The
    // insertion callback will handle all other cases.
    // FIXME: this is left over from GlyphIterator, but there's no easy
    // way to implement this here... it seems that GlyphIterator doesn't
    // really need it 'cause the insertions don't get  applied until after a
    // complete pass over the glyphs, after which the iterator gets reset anyhow...
    // probably better to just document that for LEGlyphStorage and GlyphIterator...
    if (position == glyphCount) {
        position = newGlyphCount;
    }
#endif

    fInsertionList->applyInsertions(this);

    fInsertionList->reset();

    return fGlyphCount = newGlyphCount;
}

le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
{
#if 0
    // if the current position is within the block we're shifting
    // it needs to be updated to the current glyph's
    // new location.
    // FIXME: this is left over from GlyphIterator, but there's no easy
    // way to implement this here... it seems that GlyphIterator doesn't
    // really need it 'cause the insertions don't get  applied until after a
    // complete pass over the glyphs, after which the iterator gets reset anyhow...
    // probably better to just document that for LEGlyphStorage and GlyphIterator...
    if (position >= atPosition && position <= fSrcIndex) {
        position += fDestIndex - fSrcIndex;
    }
#endif

    if (fAuxData != NULL) {
        le_int32 src = fSrcIndex, dest = fDestIndex;

        while (src > atPosition) {
            fAuxData[dest--] = fAuxData[src--];
        }

        for (le_int32 i = count - 1; i >= 0; i -= 1) {
            fAuxData[dest--] = fAuxData[atPosition];
        }
    }

    while (fSrcIndex > atPosition) {
        fGlyphs[fDestIndex]      = fGlyphs[fSrcIndex];
        fCharIndices[fDestIndex] = fCharIndices[fSrcIndex];

        fDestIndex -= 1;
        fSrcIndex  -= 1;
    }

    for (le_int32 i = count - 1; i >= 0; i -= 1) {
        fGlyphs[fDestIndex]      = newGlyphs[i];
        fCharIndices[fDestIndex] = fCharIndices[atPosition];

        fDestIndex -= 1;
    }

    // the source glyph we're pointing at
    // just got replaced by the insertion
    fSrcIndex -= 1;

    return FALSE;
}

U_NAMESPACE_END

