/** \file lowlevel_indexrepository.cpp .
-----------------------------------------------------------------------------


 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.

-----------------------------------------------------------------------------

   Description:

-----------------------------------------------------------------------------


-------------------------------------------------------------------------- */

//#define DEBUG_VERBOSE
/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"

#include "uima/macros.h"

#include "uima/lowlevel_indexrepository.hpp"
#include "uima/lowlevel_index.hpp"
#include "uima/lowlevel_indexiterator.hpp"
#include "uima/lowlevel_internal_indexfactory.hpp"
#include "uima/internal_fspromoter.hpp"
#include "uima/engine.hpp"
#include "uima/msg.h"
/* ----------------------------------------------------------------------- */
/*       Constants                                                         */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Forward declarations                                              */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Types / Classes                                                   */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Implementation                                                    */
/* ----------------------------------------------------------------------- */

namespace uima {
  namespace lowlevel {

    IndexRepository::IndexRepository(IndexDefinition const & indexDef,
                                     uima::lowlevel::FSHeap & rFSHeap,
                                     CAS & cas)
        : iv_indexDefinition(indexDef),
        iv_cas(cas),
        iv_rFSHeap(rFSHeap),
        iv_bIsInitialized(false) {
      init();
    }

    void IndexRepository::init() {

      UIMA_TPRINT("constructing index store");
      iv_bIsInitialized = false;
      assert( !iv_bIsInitialized );

      iv_idMaximalTypeMapping.clear();
      iv_idNonMaximalTypeIndexes.clear();
      iv_indexes.clear();
      iv_cacheDirtyFlags.clear();
      iv_isUsed.clear();
      iv_usedIndexes.clear();

      size_t typeNum = iv_rFSHeap.getTypeSystem().getNumberOfTypes();
      iv_idMaximalTypeMapping.resize( typeNum + 1 );
      iv_indexes.resize( typeNum + 1);
      iv_idNonMaximalTypeIndexes.resize( typeNum + 1 );
      iv_cacheDirtyFlags.resize(typeNum+1);
      iv_isUsed.assign(typeNum+1, false);
      iv_bIsInitialized = true;
      UIMA_TPRINT("index store constructed");

      assert( iv_bIsInitialized );

      vector<IndexDefinition::TyIndexID> ids;
      iv_indexDefinition.getAllIndexIDs(ids);

      size_t i;

      for (i=0; i<ids.size(); ++i) {

        IndexDefinition::TyIndexID const & id = ids[i];
        uima::lowlevel::TyFSType indexType = iv_indexDefinition.getTypeForIndex(id);
        uima::lowlevel::internal::IndexFactory const * factory = iv_indexDefinition.getFactory(id);
        assert( EXISTS(factory) );

        vector<TyFSType> subsumedTypes;
        iv_indexDefinition.getTypeSystem().getSubsumedTypes(indexType, subsumedTypes);
        size_t i;
        // create the single indexes
        for (i=0; i<subsumedTypes.size(); ++i) {
          TyFSType type = subsumedTypes[i];
          internal::SingleIndex* ix = factory->createSingleIndex(*this, type);
          assert( type < iv_indexes.size() );
          iv_idMaximalTypeMapping[type][id] = iv_indexes[type].size();
          iv_indexes[type].push_back(ix);
        }

        // create all composite indexes
        for (i=0; i<subsumedTypes.size(); ++i) {
          TyFSType type = subsumedTypes[i];
          if (!iv_indexDefinition.getTypeSystem().isMaximalType(type)) {
            UIMA_TPRINT("creating index for non maximal type");
            internal::CompositeIndex* compIx = factory->createCompositeIndex(*this, type);
            iv_idNonMaximalTypeIndexes[type][id] = compIx;
            // add single indexes
            vector<TyFSType> subsumedTypes2;
            iv_indexDefinition.getTypeSystem().getSubsumedTypes(type, subsumedTypes2);
            size_t j;
            for (j=0; j<subsumedTypes2.size(); ++j) {
              TyFSType subsType = subsumedTypes2[j];
              assert( iv_idMaximalTypeMapping[subsType].find(id) != iv_idMaximalTypeMapping[subsType].end() );
              size_t pos = iv_idMaximalTypeMapping[subsType][id];
              compIx->addComponent( iv_indexes[subsType][pos] );
              UIMA_TPRINT("Adding single index of type " << iv_indexDefinition.getTypeSystem().getTypeName(subsType) );
            }
          }
        }
      }
    }


    IndexRepository::~IndexRepository() {
      clearAll();
    }

    void IndexRepository::clearAll() {
      size_t i,j;

      // delete indexes
      for (i=0; i<iv_indexes.size(); ++i) {
        for (j=0; j<iv_indexes[i].size(); ++j) {
          delete iv_indexes[i][j];
        }
      }
      // delete idNonMaximalTypeIndexes
      for (i=0; i<iv_idNonMaximalTypeIndexes.size(); ++i) {
        map<IndexDefinition::TyIndexID, internal::CompositeIndex*>::iterator it;
        for (it = iv_idNonMaximalTypeIndexes[i].begin(); it != iv_idNonMaximalTypeIndexes[i].end(); ++it) {
          delete (*it).second;
        }
      }

      iv_idMaximalTypeMapping.clear();
      iv_idNonMaximalTypeIndexes.clear();
      iv_indexes.clear();
      iv_cacheDirtyFlags.clear();
    }


    void IndexRepository::getUsedIndexes(vector<TyFSType>& fillit) {
      fillit.clear();
      fillit.assign(iv_usedIndexes.begin(), iv_usedIndexes.end());
    }

	void IndexRepository::getIndexedFSs(vector<TyFS>& fillit) {
      fillit.clear();
      for (size_t i=0;i < iv_undefinedindex.size(); i++ ) {
            TyFS tyFSHeapIndex = this->iv_undefinedindex[i];
            fillit.push_back(tyFSHeapIndex);
      }
	  for (size_t i=0; i<iv_usedIndexes.size(); ++i) {
          vector<uima::lowlevel::internal::SingleIndex*> const & crSingleIndexes =
            getAllSingleIndexesForType(iv_usedIndexes[i]);
          for (size_t j=0; j<crSingleIndexes.size(); ++j) {
            auto_ptr<uima::lowlevel::IndexIterator> apIt(crSingleIndexes[j]->createIterator());
            for (apIt->moveToFirst(); apIt->isValid(); apIt->moveToNext()) {
              uima::lowlevel::TyHeapCell pHeapCell = (uima::lowlevel::TyHeapCell) apIt->get();
              TyFS tyFSHeapIndex =  pHeapCell;
              fillit.push_back( tyFSHeapIndex );
            }
          }
      }
	  // eliminate duplicates
      sort(fillit.begin(), fillit.end());
      vector<TyFS>::iterator end = unique(fillit.begin(), fillit.end());
    }

    void IndexRepository::reset() {

      // clear undefined index
      iv_undefinedindex.clear();

      // check if anything to do
      if ( 0 == iv_usedIndexes.size())
        return;

      // Reset the indexes used
      for (size_t i=0; i<iv_usedIndexes.size(); ++i) {
        vector<uima::lowlevel::internal::SingleIndex*> const & crSingleIndexes = getAllSingleIndexesForType(iv_usedIndexes[i]);
        for (size_t j=0; j<crSingleIndexes.size(); ++j) {
          crSingleIndexes[j]->reset();
        }
        iv_cacheDirtyFlags[iv_usedIndexes[i]].clear();
        iv_isUsed[iv_usedIndexes[i]] = false;
      }
      iv_usedIndexes.clear();
    }


    void IndexRepository::resetDefinitions() {
      // reset all index data
      clearAll();
      init();
    }


    IndexABase const & IndexRepository::getLowlevelIndex(IndexDefinition::TyIndexID const & crID, TyFSType type) const {
      assert( iv_bIsInitialized );
      assert( iv_indexDefinition.getTypeSystem().isValidType(type) );
      assert( iv_indexDefinition.isValidIndexId(crID) );
      assert( iv_indexDefinition.getTypeSystem().subsumes( iv_indexDefinition.getTypeForIndex(crID), type) );

      IndexABase* result = NULL;
      if (iv_indexDefinition.getTypeSystem().isMaximalType(type)) {
        UIMA_TPRINT("requested index for maximal type");
        map<IndexDefinition::TyIndexID, size_t>::const_iterator cit = iv_idMaximalTypeMapping[type].find(crID);
        assert( cit != iv_idMaximalTypeMapping[type].end() );
        size_t i = (*cit).second;
        assert( (i >=0) && (i<iv_indexes[type].size()));
        result = iv_indexes[type][ i ];
      } else {
        UIMA_TPRINT("requested index for non maximal type");
        map<IndexDefinition::TyIndexID, internal::CompositeIndex*>::const_iterator cit = iv_idNonMaximalTypeIndexes[type].find(crID);
        assert( cit != iv_idNonMaximalTypeIndexes[type].end() );
        // composite index already exists
        result = (*cit).second;
      }
      assert( EXISTS(result) );
      return *result;
    }



    bool IndexRepository::contains(TyFS tyFS) const {
      assert( iv_bIsInitialized );
      TyFSType tyType = iv_rFSHeap.getType(tyFS);
      vector<internal::SingleIndex*> const & crSingleIndexes = getAllSingleIndexesForType(tyType);
      vector<internal::SingleIndex*>::const_iterator cit;
      for (cit = crSingleIndexes.begin(); cit != crSingleIndexes.end(); ++cit) {
        if ( (*cit)->contains(tyFS) ) {
          return true;
        }
      }
      return false;
    }


    void IndexRepository::add(TyFS fs) {
      assert( iv_bIsInitialized );
      TyFSType type = iv_rFSHeap.getType(fs);
      assert( iv_rFSHeap.getTypeSystem().isValidType(type) );
      UIMA_TPRINT("Adding fs of type " << iv_rFSHeap.getTypeSystem().getTypeName(type) << ": " << (int) fs);
      assert( type < iv_cacheDirtyFlags.size() );
      iv_cacheDirtyFlags[type].clear();

      assert( type < iv_indexes.size() );

      vector<internal::SingleIndex*>& typeIndexes = iv_indexes[type];

      if (!iv_isUsed[type]) {

        //if there is no index defined for this type
        if (typeIndexes.size() == 0 ) {
          iv_undefinedindex.push_back(fs);
          return;
        }

        iv_isUsed[type] = true;
        iv_usedIndexes.push_back(type);
      }


      // for all single indexes on the type of fs
      vector<internal::SingleIndex*>::iterator it;
      for (it = typeIndexes.begin(); it != typeIndexes.end(); ++it) {
        UIMA_TPRINT("index type: " << (*it)->getType());
        UIMA_TPRINT("     (" << iv_rFSHeap.getTypeSystem().getTypeName( (*it)->getType() ));
        assert( iv_rFSHeap.getTypeSystem().isValidType( (*it)->getType() ));
        assert( (*it)->getType() == type );
        (*it)->add(fs);
      }
    }


    void IndexRepository::clearDirtyFlagForIndex(IndexABase const * index) {
      assert(EXISTS(index) );
      TyFSType t = index->getType();
      assert( iv_indexDefinition.getTypeSystem().isValidType(t) );
      vector<TyFSType> types;
      iv_indexDefinition.getTypeSystem().getSubsumedTypes(t, types);
      vector<TyFSType>::const_iterator cit;
      for (cit = types.begin(); cit != types.end(); ++cit) {
        assert( (*cit) < iv_cacheDirtyFlags.size() );
        set<IndexABase const *> & rIndexSet = iv_cacheDirtyFlags[*cit];
        rIndexSet.insert(index);
      }
    }


    bool IndexRepository::isDirtyForIndex(IndexABase const * index) const {
      assert(EXISTS(index) );
      TyFSType t = index->getType();
      assert( iv_indexDefinition.getTypeSystem().isValidType(t) );
      vector<TyFSType> types;
      iv_indexDefinition.getTypeSystem().getSubsumedTypes(t, types);
      vector<TyFSType>::const_iterator cit;
      for (cit = types.begin(); cit != types.end(); ++cit) {
        assert( (*cit) < iv_cacheDirtyFlags.size() );
        set<IndexABase const *> const & crIndexSet = iv_cacheDirtyFlags[*cit];
        if ( crIndexSet.find(index) == crIndexSet.end() ) {
          return true;
        }
      }
      return false;
    }



    /*************************************************************/

#ifndef NDEBUG
    void IndexRepository::print(ostream& os) const {
      os << "===========================================" << endl;
      size_t i,j;
      for (i=1; i<iv_indexes.size(); ++i) {
        UIMA_TPRINT("index for type: " << i);
        assert( iv_indexDefinition.getTypeSystem().isValidType(i) );
        os << "Index for type " << iv_indexDefinition.getTypeSystem().getTypeName(i) << ":" << endl;
        for (j=0; j<iv_indexes[i].size(); ++j) {
          os << "  " << j << "th index: ";
          IndexABase* ix = iv_indexes[i][j];

          IndexIterator* it = ix->createIterator();
          for (it->moveToFirst(); it->isValid(); it->moveToNext() ) {
            os << (size_t) it->get()  << "  ";
          }
          os << endl;
          delete it;
        }
      }

      os << "===========================================" << endl;
    }
#endif


  }
}
/* ----------------------------------------------------------------------- */




