/***************************************************************************
**
**  This file is part of gpdistance.
**
**  gpdistance 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.
**
**  gpdistance 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: 2009-03-24
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreMath.h>

#include "gpdistanceVersion.h"
#include "gpdistanceInstallPath.h"

PACKAGE_INFO("gpdistance", GPDISTANCE)

ApplicationHelp * help();

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

  // Options
  QString coordinateFile;
  bool doAll=false;
  // Check arguments
  int i, j=1;
  for(i=1; i<argc; i++) {
    QByteArray arg=argv[i];
    if(arg[0]=='-') {
      if(arg=="-c") {
        CoreApplication::checkOptionArg(i, argc, argv);
        coordinateFile=argv[i];
      } else if(arg=="-all") {
        doAll=true;
      } else {
        App::log(tr("gpdistance: 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(coordinateFile.isEmpty()) {
    App::log(tr("gpdistance: missing coordinate file (option -c).\n") );
    return 2;
  }
  QFile fCoord(coordinateFile);
  if( ! fCoord.open(QIODevice::ReadOnly) ) {
    App::log(tr("gpdistance: cannot read file %1.\n").arg(coordinateFile) );
    return 2;
  }
  QTextStream sCoord(&fCoord);
  LineParser p;
  QMap<QString,Point> points;
  bool ok=true;
  int iLine=0;
  while( ! sCoord.atEnd()) {
    QString l=sCoord.readLine();
    iLine++;
    if(!l.isEmpty() && l[0]!='#') {
      p.setString(l);
      double x=p.toDouble(0, ok);
      double y=p.toDouble(1, ok);
      double z=p.toDouble(2, ok);
      QString stationName=p.toString(3, ok);
      if( !ok) {
        App::log(tr("gpdistance: error reading file %1 at line %2\n").arg(coordinateFile).arg(iLine) );
        return 2;
      }
      points.insert(stationName, Point(x, y, z) );
    }
  }

  QTextStream sOut(stdout);
  if(doAll) {
    for(QMap<QString,Point>::iterator it1=points.begin();it1!=points.end();it1++) {
      for(QMap<QString,Point>::iterator it2=points.begin();it2!=points.end();it2++) {
        if(it1==it2) break;
        Point& p1=it1.value();
        Point& p2=it2.value();
        sOut << it1.key() << " " << it2.key() << " " << p1.distanceTo(p2) << " " << Angle::mathToGeographic(p1.azimuthTo(p2)) << endl;
      }
    }
  } else {
    while(!feof(stdin)) {
      QString l=File::readLine(true);
      if(l=="exit" || l=="quit") break;
      if(!l.isEmpty() && l[0]!='#') {
        p.setString(l);
        QString station1=p.toString(0, ok);
        QString station2=p.toString(1, ok);
        if( !ok) {
          App::log(tr("gpdistance: error reading station_name_1 station_name_2\n") );
          return 2;
        }
        QMap<QString,Point>::iterator it;
        it=points.find(station1);
        if(it==points.end()) {
          App::log(tr("gpdistance: unknown station name: %1\n").arg(station1) );
          return 2;
        }
        Point p1=it.value();
        it=points.find(station2);
        if(it==points.end()) {
          App::log(tr("gpdistance: unknown station name: %1\n").arg(station2) );
          return 2;
        }
        Point p2=it.value();
        sOut << station1 << " " << station2 << " " << p1.distanceTo(p2) << " " << Angle::mathToGeographic(p1.azimuthTo(p2)) << endl;
      }
    }
  }
  return 0;
}

ApplicationHelp * help()
{
  TRACE;
  ApplicationHelp * h=new ApplicationHelp;
  h->setOptionSummary( "[OPTIONS]" );
  h->setComments( "Calculate distances between stations. Couples of station names are passed throught "
                  "stdin with a two-column format: station_name_1 station_name_2.\n"
                  "Output: station_name_1 station_name_2 distance azimuth (from North=Y axis)." );
  h->addGroup("gpdistance", "gpdistance");
  h->addOption("-c <COORD>","Coordinate file: X Y Z station_name");
  h->addOption("-all","Calculates distances and azimuths betwwen all pairs");
  h->addExample("echo \"WAU01 WAU02\" | gpdistance -c array.coord", "Print distance between stations WAU01 and WAU02");
  return h;
}
