/*******************************************************************************
 * Copyright (C) 1996-1999, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
//=============================================================================
//
// File mergecol.cpp
//
// Contains MergeCollation.  This classes job is to take one or more
// strings that represent the orderings in a collation, in the form 
// "a , A < b , B ....".  MergeCollation parses the string into a list of
// PatternEntry objects that are sorted by their position in the collation
// ordering.  The input string is allowed to have elements out of order, e.g.
// "... b < c < d < e .....   c < ch".  After being parsed by MergeCollation,
// the pattern entries will be in the proper order: "b", "c", "ch", "d", "e"
//
// Created by: Helena Shih
//
// Modification History:
//
//  Date        Name        Description
//  3/5/97      mark        Cleaned up fixEntry().  Added constants BYTEPOWER
//                          and BYTEMASK to replace BYTESIZE.
//  6/17/97     helena      In getPattern, added the queue-up list for entries 
//                          with the same extension chars.
//  6/23/97     helena      Adding comments to make code more readable.
//  8/13/98     erm         Synched up with 1.2 version of MergeCollation.java
// 04/23/99     stephen     Removed EDecompositionMode, merged with
//                          Normalizer::EMode
//=============================================================================

#include "mergecol.h"

#include "tables.h"

#ifdef _DEBUG
#include "unistrm.h"
#endif

const   int32_t         MergeCollation::BITARRAYSIZE = 8192;
const   uint8_t         MergeCollation::BITARRAYMASK = 0x1;
const   int32_t         MergeCollation::BYTEPOWER = 3;
const   int32_t         MergeCollation::BYTEMASK = (1 << BYTEPOWER) - 1;

 /**
 * Creates from a pattern.
 * If the input pattern is incorrect, error code will be set.
 * @param pattern the merge collation pattern
 * @param success error code input/output parameter.
 */
MergeCollation::MergeCollation(const    UnicodeString&  pattern,
                               Normalizer::EMode decompMode,
                   UErrorCode&      status)
    : lastEntry(NULL), saveEntry(NULL)
{
  patterns = new VectorOfPointersToPatternEntry();
  
  
  if (patterns == NULL)
    {
      status = U_MEMORY_ALLOCATION_ERROR;
      return;
    }

  statusArray = new uint8_t[BITARRAYSIZE];

  if (statusArray == NULL)
    {
      delete patterns;
      status = U_MEMORY_ALLOCATION_ERROR;
      return;
    }

  int32_t i;
  for (i = 0; i < BITARRAYSIZE; i += 1)
    {
      statusArray[i] = 0;
    }

  setPattern(pattern, decompMode, status);
  if (U_FAILURE(status))
    {
      delete [] statusArray;
      statusArray = NULL;
    }
}

/**
 * Copy constructor
 * @param other the source merge collation object to be constructed with
 */
MergeCollation::MergeCollation(const    MergeCollation& other)
    : lastEntry(NULL), saveEntry(NULL)
{
  // This copy ctor does a deep copy - it duplicates the PatternEntry
  // objects as well as the vector object
  patterns = new VectorOfPointersToPatternEntry(*other.patterns);

  int32_t i;
  statusArray = new uint8_t[BITARRAYSIZE];
  for (i = 0; i < BITARRAYSIZE; i += 1)
    {
      statusArray[i] = other.statusArray[i];
    }
}

// Assignment operator.  Does a deep copy.
const MergeCollation&
MergeCollation::operator=(const MergeCollation& other)
{
  if (this != &other)
  {
    *patterns = *other.patterns;
    lastEntry = 0;
    saveEntry = 0;

    int32_t i;
    for (i = 0; i < BITARRAYSIZE; i += 1)
    {
      statusArray[i] = other.statusArray[i];
    }
  }

  return *this;
}

/**
 * Destructor
 */
MergeCollation::~MergeCollation()
{
  delete patterns;
  delete [] statusArray;
}

/**
 * recovers current pattern as a string.
 * Basically, this runs through the PatternEntry array and outputs
 * @param result the string into which the pattern is recovered
 * the proper string for each element.
 * @param withWhiteSpace puts spacing around the entries, and \n
 * before & and <
 */
UnicodeString&
MergeCollation::getPattern(UnicodeString& result, UBool withWhiteSpace) const
{

  int32_t i;
  PatternEntry *tmp = NULL;
  VectorOfPointer *extList = NULL;

  result.remove();

  for (i = 0; i < patterns->size(); i += 1)
    {
      PatternEntry* entry = patterns->at(i);

      if (entry != NULL)
    {
      // if the entry is an expanding ligature, queue up the entries until
      // the last same ligature has been processed.
      if (entry->extension.length() != 0)
        {
          if (extList == NULL)
        {
          extList = new VectorOfPointer();
        }

          extList->atInsert(extList->size(), (const void*&)entry);
            }
      else
        {
          // Process the queue-up list in reverse order to get the correct
          // pattern.
          if (extList != NULL)
        {
          const PatternEntry *last = findLastWithNoExtension(i - 1);

          for (int32_t j = extList->size() - 1; j >= 0 ; j -= 1)
            {
              tmp = (PatternEntry*)(extList->at(j));
              tmp->addToBuffer(result, FALSE, withWhiteSpace, last);
                    }

          delete extList;
          extList = NULL;
                }

          entry->addToBuffer(result, FALSE, withWhiteSpace, NULL);
            }
        }
    }

  // Complete the queue-up list if it isn't empty
  if (extList != NULL)
    {
      const PatternEntry *last = findLastWithNoExtension(i - 1);

      for (int32_t j = extList->size() - 1; j >= 0 ; j -= 1)
    {
      tmp = (PatternEntry*)(extList->at(j));
      tmp->addToBuffer(result, FALSE, withWhiteSpace, last);
        }

      delete extList;
    }


  return result;
} 

/**
 * emits the pattern for collation builder.
 * @param result the string into which the pattern is recovered
 * @param withWhiteSpace puts spacing around the entries, and \n
 * before & and <
 * @return emits the string in the format understable to the collation
 * builder.
 */
UnicodeString&
MergeCollation::emitPattern(UnicodeString& result, UBool withWhiteSpace) const 
{
  int32_t i;

  result.remove();

  for (i = 0; i < patterns->size(); i += 1)
    {
      PatternEntry *entry = (PatternEntry *)patterns->at(i);

      if (entry != NULL)
    {
      entry->addToBuffer(result, TRUE, withWhiteSpace, NULL);
        }
    }

  return result;
}

/**
 * sets the pattern.
 */
void MergeCollation::setPattern(const   UnicodeString&  pattern,
                                Normalizer::EMode decompMode,
                UErrorCode&      success)
{
  if (U_FAILURE(success))
    {
      return;
    }

  patterns->clear();

  addPattern(pattern, decompMode, success);
  if (U_FAILURE(success))
    {
      delete patterns;
      patterns = NULL;
    }
}

/**
 * adds a pattern string to the current list of patterns
 * @param pattern the new pattern to be added
 */
void MergeCollation::addPattern(const   UnicodeString&  pattern,
                                Normalizer::EMode decompMode,
                UErrorCode&      success)
{
  if (U_FAILURE(success) || (pattern.length() == 0))
    {
      return;
    }

  PatternEntry::Parser *parser = new PatternEntry::Parser(pattern, decompMode);
    
  PatternEntry *entry = parser->next(success);

  while (entry != NULL)
    {
      if (U_FAILURE(success))
    {
      delete entry;
      break;
    }

      fixEntry(entry, success);

      if (U_FAILURE(success))
    {
      delete entry;
      break;
    }

      entry = parser->next(success);
    }
}

/**
 * gets count of separate entries
 * @return the size of pattern entries
 */
int32_t 
MergeCollation::getCount() const {
  return patterns->size();
}   

/**
 * gets count of separate entries
 * @param index the offset of the desired pattern entry
 * @return the requested pattern entry
 */
const PatternEntry* MergeCollation::getItemAt(UTextOffset index) const {
  return patterns->at(index);
}

// Find the last no-extension entry.
const PatternEntry* MergeCollation::findLastWithNoExtension(int32_t i) const {
  for (--i;i >= 0; --i) {
    PatternEntry* entry = patterns->at(i);
    if ((entry != 0) && (entry->extension.length() == 0)) {
      return entry;
    }
  }
  return 0;
}

// Add a new PatternEntry to this MergeCollation's ordered list
// of entries.
//
// If the strength is RESET, then just change the lastEntry to
// be the current. (If the current is not in patterns, signal an error).
//
// If not, then remove the current entry, and add it after lastEntry
// (which is usually at the end).
//
void MergeCollation::fixEntry(PatternEntry* newEntry,
                              UErrorCode&    success)
{
  UnicodeString excess;
  UBool changeLastEntry = TRUE;

  if (newEntry->strength != PatternEntry::RESET)
    {
      int32_t oldIndex = -1;

      // Use statusArray to mark if a unicode character has been
      // added in the table or not.  The same later entry will 
      // replace the previous one.  This will improve the single
      // char entries dramatically which is the majority of the 
      // entries.
      if (newEntry->chars.length() == 1)
    {
      UChar c = newEntry->chars[0];
      int32_t statusIndex = c >> BYTEPOWER;
      uint8_t bitClump = statusArray[statusIndex];
      uint8_t setBit = BITARRAYMASK << (c & BYTEMASK);

      if (bitClump != 0 && (bitClump & setBit) != 0)
            {
          int32_t i = 0;

          // Find the previous entry with the same key
          for (i = patterns->size() - 1; i >= 0; i -= 1)
        {
          PatternEntry *entry = patterns->at(i);

          if ((entry != 0) &&
              (entry->chars == newEntry->chars))
            {
              oldIndex = i;
              break;
                    }
                }
        }
      else
        {
          // We're going to add an element that starts with this
          // character, so go ahead and set its bit.
          statusArray[statusIndex] = (uint8_t)(bitClump | setBit);
            } 
        }
      else
    {
      oldIndex = patterns->lastIndexOf(newEntry);
        }

      if (oldIndex != -1)
    {
      PatternEntry *p = patterns->orphanAt(oldIndex);
      delete p;
        }

      // Find the insertion point for the new entry.
      int32_t lastIndex = findLastEntry(lastEntry, excess, success);

      if (U_FAILURE(success))
    {
      return;
    }

      // Do not change the last entry if the new entry is a expanding character
      if (excess.length() != 0)
    {
      // newEntry.extension = excess + newEntry.extensions;
      newEntry->extension.insert(0, excess);
      if (lastIndex != patterns->size())
        {
          lastEntry = saveEntry;
          changeLastEntry = FALSE;
            }
        }

      // Add the entry at the end or insert it in the middle
      if (lastIndex == patterns->size())
    {
      patterns->atPut(lastIndex, newEntry);
      saveEntry = newEntry;

        }
      else
    {
      patterns->atInsert(lastIndex, newEntry);  // add at end
        }
    }
    
  if (changeLastEntry)
    {
      lastEntry = newEntry;
    }
}

int32_t
MergeCollation::findLastEntry(const PatternEntry*   lastEntry,
                  UnicodeString&  excess,
                  UErrorCode&      success) const
{
  if (U_FAILURE(success))
    {
      return -1;
    }

  if (lastEntry == NULL)
    {
      return 0;
    }
  else if (lastEntry->strength != PatternEntry::RESET)
    {
      int32_t oldIndex = -1;

      // If the last entry is a single char entry and has been installed, 
      // that means the last index is the real last index.
      if (lastEntry->chars.length() == 1)
    {
      int32_t index = lastEntry->chars[0] >> BYTEPOWER;

      if ((statusArray[index] & 
           (uint8_t)(BITARRAYMASK << (lastEntry->chars[0] & BYTEMASK))) != 0)
        {
          oldIndex = patterns->lastIndexOf(lastEntry);
            }
        }
      else
    {
      oldIndex = patterns->lastIndexOf(lastEntry);
        }

      // must exist!
      if (oldIndex == -1)
    {
      success = U_INVALID_FORMAT_ERROR;
      return oldIndex;
        }

      return oldIndex + 1;
    }
  else
    {
      // We're doing a reset, i.e. inserting a new ordering at the position
      // just after the entry corresponding to lastEntry's first character
      int32_t i;

      // Search backwards for string that contains this one;
      // most likely entry is last one
      for (i = patterns->size() - 1; i >= 0; i -= 1)
    {
      PatternEntry* entry = patterns->at(i);
      UnicodeString buffer;
      if (entry != 0)
        {
          //
          // Look for elements with the same beginning key.  The extra
          // characters will be the expanding portion.  This handles cases like
          // "& Question-mark < '?'".  We find the existing PatternEntry that matches
          // the longest possible substring of "Question-mark", which will probably
          // be 'Q'.  We save the characters that didn't match ("uestion-mark" in
          // this case), and then return the next index.
          //
          if (entry->chars.compareBetween(0, entry->chars.length(),
                          lastEntry->chars,0,entry->chars.length()) == 0)
        {
          lastEntry->chars.extractBetween(entry->chars.length(), 
                          lastEntry->chars.length(),
                          buffer);
          excess += buffer;
          break;
                }
        }
        }

      if (i == -1)
    {
      success = U_INVALID_FORMAT_ERROR;
      return i;
        }

      return i + 1;
    }
}
