/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2010-07-27
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "SortedVector.h"

namespace QGpCoreTools {

  /*!
    \class SortedVector SortedVector.h
    \brief A vector of sorted elements

    Provides fast lookup (equivalent to QMap) on vector based storage.
    Probably less memory consumption than a QMap but slower insertions.
  */

  /*!
    \fn int SortedVector::indexOf(const T& o) const

    Returns the index of \a o or -1 if \a o does not exist.
  */

  /*!
    \fn int SortedVector::indexAfter(const T& o) const

    Returns the index right after \a o. Returned index can range from 0 to count().
  */

  /*!
    \fn void SortedVector::append(T * o)

    Adds object \a o to the end of the vector. The vector is not automatically sorted
    and search functions cannot be used before a proper initialization of all object
    keys and a call to sort(). This function may be of interest if keys are not
    available at the time of insertion.
  */

  /*!
    \fn void SortedVector::sort()

    Sort the obects. This function is required only when object are added using append().
    On the contrary, insert() keeps the vector properly sorted.
  */

#ifdef SORTED_VECTOR_TEST
  bool testSortedVerctor()
  {
    class Test
    {
    public:
      Test(int key, int tag) {_key=key; _tag=tag;}

      int key() const {return _key;}
      int tag() const {return _tag;}
    private:
      int _key, _tag;
    };

    SortedVector<int, Test> v;
    /*
    int keys[]={1824955210, 1766864916, 716599088, 311655150, 2106038869,
                1095222024, 561455035, 229775917, 437532857, 730174109,
                299548759, 711185569, 505424647, 1400468129, 939542407,
                1146199365, 1621666167, 1345294455, 439969358, 977584325,
                515594596, 1515919191, 875888668, 1683670957, 169756838,
                1228976953, 458553961, 2073128325, 793602655, 807410395};
    */

    // Check insertion
    for(int i=0; i<3000; i++) {
      //int k=keys[i];
      int k=rand();
      v.insert(new Test(k, i*3+1));
      v.insert(new Test(k, i*3+2));
      v.insert(new Test(k, i*3+3));
    }
    // Check of insert and firstIndexAfter
    for(int i=0; i<v.count(); i++) {
      qDebug() << i << v.at(i)->key() << v.at(i)->tag();
    }
    for(int i=1; i<v.count(); i++) {
      if(v.at(i-1)->key()>v.at(i)->key()) {
        v.clear(true);
        return false;
      } else if(v.at(i-1)->key()==v.at(i)->key()) {
        if(v.at(i-1)->tag()>v.at(i)->tag()) {
          v.clear(true);
          return false;
        }
      }
    }
    // Check firstIndexOf
    v.firstIndexOf(v.at(v.count()-1)->key());
    for(int d=-1; d<=1; d++) {
      for(int i=0; i<v.count(); i++) {
        int index=v.firstIndexOf(v.at(i)->key()+d);
        if(d==0) {
          if(index!=i) {
            if(v.at(index)->key()==v.at(i)->key()) {
              if(index==0 || v.at(index-1)->key()!=v.at(i)->key()) {
                continue;
              }
            }
            v.clear(true);
            return false;
          }
        } else {
          if(index!=-1) {
            v.clear(true);
            return false;
          }
        }
      }
    }
    v.clear(true);
    qDebug() << "SortedVector checked successfully.";
    return true;
  }
#endif

} // namespace QGpCoreTools
