/***************************************************************************
**
**  This file is part of gpsort.
**
**  gpsort is free software: you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation, either version 3 of the License, or
**  (at your option) any later version.
**
**  gpsort 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 General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2007-05-22
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreMath.h>

#include "gpsortVersion.h"
#include "gpsortInstallPath.h"

PACKAGE_INFO("gpsort", GPSORT)

ApplicationHelp * help();

template<class PointType> int sortCurve(bool explicitIndexList, int& argc, char ** argv)
{
  // Read stdin for curves until encountering a blank line
  QString buf;

  QStringList curveComments;
  curveComments.append(QString());
  QString * curveComment=&curveComments.last();

  QList< Curve<PointType> > curves;
  curves.append(Curve<PointType>());
  Curve<PointType> * curve=&curves.last();

  PointType p;
  QTextStream sIn(stdin);
  QTextStream sOut(stdout);
  CoreApplication::instance()->debugUserInterrupts(false);
  while(!sIn.atEnd()) {
    buf=sIn.readLine();
    if(buf[0]=='\n' || buf[0]=='#') {
      if(!curve->isEmpty()) {
        curveComments.append(buf+"\n" );
        curveComment=&curveComments.last();
        curves.append(Curve<PointType>());
        curve=&curves.last();
      } else {
        curveComment->append(buf+"\n");
      }
    } else {
      QString str(buf);
      p.fromString(str);
      curve->append(p);
    }
  }
  CoreApplication::instance()->debugUserInterrupts(true);

  // Output in sected order
  QSet<int> indexes;
  for(int i=1 ; i<argc; i++) {
    int index=atoi(argv[i] );
    if(index<curves.count()) {
      sOut << "# curve's original index: " << index << "\n"
           << curveComments.at(index)
           << curves.at(index).toString();
      indexes.insert(index);
    } else {
      App::log(tr("gpsort: index %1 out of range\n").arg(index) );
      return 2;
    }
  }
  if(!explicitIndexList) {
    for(int i=0; i< curves.count();i++) {
      if(!indexes.contains(i)) {
        sOut << "# curve's original index: " << i << "\n"
             << curveComments.at(i)
             << curves.at(i).toString();
      }
    }
  }
  return 0;
}

int main(int argc, char ** argv)
{
  CoreApplication a(argc, argv, help);

  // Options
  bool explicitIndexList=false;
  bool namedPoint=false;
  // Check arguments
  int i, j=1;
  for(i=1; i<argc; i++) {
    QByteArray arg=argv[i];
    if(arg[0]=='-') {
      if(arg=="-explicit") {
        explicitIndexList=true;
      } else if(arg=="-cn") {
          namedPoint=true;
      } else {
        App::log(tr("gpsort: bad option %1, see -help\n").arg(argv[i]) );
        return 2;
      }
    } else {
      argv[j++]=argv[i];
    }
  }
  if(j < argc) {
    argv[j]=nullptr;
    argc=j;
  }

  if(namedPoint) {
    return sortCurve<NamedPoint>(explicitIndexList, argc, argv);
  } else {
    return sortCurve<PointND>(explicitIndexList, argc, argv);
  }
}

ApplicationHelp * help()
{
  ApplicationHelp * h=new ApplicationHelp;
  h->setOptionSummary( "[OPTIONS] [INDEX0 [INDEX1 ...]]" );
  h->setComments( "Take curves as input through stdin and output them in order given by index0, index1,... "
                  "The first curve has index 0.");
  h->addGroup("Gpsort","gpsort");
  h->addOption("-explicit", "If the list of indexes does not contain the index of all curves, the missing ones are "
                            "not streamed through the stdout.");
  h->addOption("-cn", "Input is considered as X Y Z Name");
  h->addExample("gpdc -R 3 -L 3 < test.model | gpsort 0 3 1 4 2 5 | figue -c -m dc.mkup -cpp 2", "Create three plots containing Rayleigh and Love curves for mode 0, 1 and 2. Original order for curves from gpdc is 3 Rayleigh modes and 3 Love modes.");
  return h;
}
