/***************************************************************************
                          locator.cpp  -  description
                             -------------------
    begin                : vie feb 7 2003
    copyright            : (C) 2003 by Jaime Robles
    email                : jaime@kde.org
 ***************************************************************************/

/******************************************************************************
 *                                                                            *
 *   This program 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 2 of the License, or        *
 *   (at your option) any later version.                                      *
 *                                                                            *
 *   This program 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 this program; if not, write to the Free Software              *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*
 *****************************************************************************/
#include <klocale.h>
//#include <kdebug.h>
//#include <ostream.h>
#include "locator.h"


Locator::Locator(){
  ideg = 0;
  imin = 0;
  isec = 0;
}

Locator::~Locator(){
}

bool Locator::isValidLocator(const QString& tlocator){
/* -------------- Subroutine -----------------------
      Check valid locator
      Input : char *locator = 4 or 6 characters word wide locator.
      returned value ==  -1 No error. (Valid locator).
      returned value ==  0 Error.   (Invalid locator).
      Note: also string "END" is considered a valid locator, but returned value is -2.
   ------------------------------------------------- */

//  valid = true; /* Assumes locator is right */
  int lenght_of_locator,i;
//  char t;
  testLocator ="A";
  testLocator = tlocator;
  lenght_of_locator = testLocator.length();
  
  if (lenght_of_locator == 4){
    testLocator = testLocator +"LM";
    lenght_of_locator = 6;
  }/* Adjust to middle of square */

  else if (lenght_of_locator != 6) return false;                /* force to 0 if locator is wrong */
  else for(i=0; i<=5; i++){
    theChar = testLocator.at(i);
    
    if(((theChar > 'R') || (theChar < 'A')) && ((i==0) || (i==1))) return false;  /* first 2 characters: from A to R */
    if(((theChar > '9') || (theChar < '0')) && ((i==2) || (i==3))) return false;  /* check the numbers  */
    if(((theChar > 'X') || (theChar < 'A')) && ((i==4) || (i==5))) return false;  /* last 2 characters: from A to X */
  }
  return true;
}


double Locator::getLat(const QString& tlocator){
if (isValidLocator(tlocator)){
  return -90+((double)tlocator.at(1)-65)*10 + ((double)tlocator.at(3)-48) +((double)tlocator.at(5)-64.5)/24;
}else
  return 0.0;  
}

double Locator::getLon(const QString& tlocator){
  if (isValidLocator(tlocator)){
    return -(-180+((double)tlocator.at(0)-65)*20 + ((double)tlocator.at(2)-48)*2 +((double)tlocator.at(4)-64.5)/12);
  }else
    return 0.0;
  
}

int Locator::getBeam(const double lon1, const double lat1, const double lon2, const double lat2){
  double lon_a,lat_a,lon_b,lat_b, bearing;
  lon_a=lon1*PI/180;   // Convert degrees to radians
  lat_a=lat1*PI/180;
  lon_b=lon2*PI/180;
  lat_b=lat2*PI/180;

//earing_Distance( double lon_a, double lat_a, /* Lon/Lat of point A */
//                  double lon_b, double lat_b, /* Lon/Lat of point B */
//                  double *bearing, double *distance )/* From A to B */
//{
  double
    gc_arc, cos_gc_arc,       /* Great circle arc   A to B */
    cos_bearing, sin_bearing, /* cos/sin of bearing A to B */
    lon_diff;                 /* Difference in longitude of B from A */

  /* Longitude differnce of B from A */
  lon_diff = lon_b - lon_a;

  /* Calculate great circle distance A to B */
  cos_gc_arc = cos(lon_diff)*cos(lat_a)*cos(lat_b) + sin(lat_a)*sin(lat_b);
  gc_arc = acos( cos_gc_arc );

  /* Distance in km */
//  *distance = eradius * gc_arc;

  /* Calculate bearing A to B */
  cos_bearing  = sin(lat_b) - sin(lat_a) * cos_gc_arc;
  sin_bearing  = sin(lon_diff) * cos(lat_a) * cos(lat_b);
  bearing = atan2(sin_bearing, cos_bearing);

  /* Correct negative (anticlockwise) bearings */
  
  if( bearing < 0.0 )
    bearing = (2*PI) + bearing;
  bearing = 360-(180/PI*bearing);

  /* Convert to degrees */
  return (int)bearing;


}

int Locator::getDistanceKilometres(const double lon1, const double lat1, const double lon2, const double lat2){
  double lo1,la1,lo2,la2;

  lo1=lon1*PI/180;   // Convert degrees to radians
  la1=lat1*PI/180;
  lo2=lon2*PI/180;  
  la2=lat2*PI/180;

// Calculates distance in km
  return  (int)(acos(cos(la1)*cos(lo1)*cos(la2)*cos(lo2)+cos(la1)*sin(lo1)*cos(la2)*sin(lo2)+sin(la1)*sin(la2)) * EARTH_RADIUS);

}

int Locator::getDistanceMilles(const double lon1, const double lat1, const double lon2, const double lat2){
  return  (int)(getDistanceKilometres(lon1, lat1, lon2, lat2)/1.609) ;

}

QString Locator::getLocator(const double lon1, const double lat1) const{
/* -------------- Subroutine -----------------------
   Calculate locator from longitude and latitude
   Input : lon = Longitude in decimal degrees (+ = West;  - = East).
           lat = Latitude in decimal degrees (+ = North; - = South).
   Output: locator = 6 characters world wide locator.
   ------------------------------------------------- */
  QString locat = ""; //NO locator

  double lo, la;
  int alo,bla,clo,dla,elo,fla;

  lo=(-lon1+180)/20;
  la = (lat1+90)/10;

  alo=(int)floor(lo);
  bla=(int)floor(la);
  lo=(lo-(double)alo)*10;
  la=(la-(double)bla)*10;

  clo = (int)floor(lo);
  dla = (int)floor(la);

  elo = (int)floor((lo-(double)clo)*24);
  fla = (int)floor((la-(double)dla)*24);

  locat.at(0)=(char)(alo+'A');
  locat.at(1)=(char)(bla+'A');
  locat.at(2)=(char)(clo+'0');
  locat.at(3)=(char)(dla+'0');
  locat.at(4)=(char)(elo+'A');
  locat.at(5)=(char)(fla+'A');


return locat;
}

void Locator::degTodms(const double deg){
  double temp;
  double ddeg;
  ddeg = 0;
  ddeg += 1.0/7200.0; /* Round-up to 0.5 sec */
  ideg = (int)ddeg;
  temp = ( deg - (double)ideg ) * 60.0;
  imin = (int)temp;
  temp = ( temp - (double)imin ) * 60.0;
  isec = (int)(temp); 
}

double Locator::dmsTodeg (int deg, int min, int sec){
    return (double)deg + (double)min/60.0 + (double)sec/3600.0;
}
