/***************************************************************************
 *
 * Project:  OpenCPN Weather Routing plugin
 * Author:   Sean D'Epagnier
 *
 ***************************************************************************
 *   Copyright (C) 2015 by Sean D'Epagnier                                 *
 *                                                                         *
 *   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 3 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.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
 ***************************************************************************
 */

#include <stdlib.h>
#include <math.h>
#include <wx/wx.h>

#include "tinyxml/tinyxml.h"

#include "Utilities.h"


double deg2rad(double degrees)
{
  return M_PI * degrees / 180.0;
}

double rad2deg(double radians)
{
  return 180.0 * radians / M_PI;
}

double heading_resolve(double degrees)
{
    while(degrees < -180)
        degrees += 360;
    while(degrees >= 180)
        degrees -= 360;
    return degrees;
}

double positive_degrees(double degrees)
{
    while(degrees < 0)
        degrees += 360;
    while(degrees >= 360)
        degrees -= 360;
    return degrees;
}

double rad2posdeg(double radians)
{
    return positive_degrees(rad2deg(radians));
}

double square(double x)
{
  return x*x;
}

double cube(double x)
{
  return x*x*x;
}

/* uh.. this is probably much slower than using some conditionals */
double average_longitude(double lon1, double lon2)
{
    double rlon1 = deg2rad(lon1), rlon2 = deg2rad(lon2);
    double x1 = cos(rlon1), x2 = cos(rlon2);
    double y1 = sin(rlon1), y2 = sin(rlon2);
    return rad2deg(atan2((y1+y2)/2, (x1+x2)/2));
}

double AttributeDouble(TiXmlElement *e, const char *name, double def)
{
    const char *attr = e->Attribute(name);
    if(!attr)
        return def;
    char *end;
    double d = strtod(attr, &end);
    if(end == attr)
        return def;
    return d;
}

int AttributeInt(TiXmlElement *e, const char *name, int def)
{
    const char *attr = e->Attribute(name);
    if(!attr)
        return def;
    char *end;
    long d = strtol(attr, &end, 10);
    if(end == attr)
        return def;
    return d;
}

bool AttributeBool(TiXmlElement *e, const char *name, bool def)
{
    return AttributeInt(e, name, def) != 0;
}

wxString calculateTimeDelta(wxDateTime startTime, wxDateTime endTime)
{
    wxString timeStr;
    if(startTime.IsValid() && endTime.IsValid())
    {
        wxTimeSpan span = endTime - startTime;
        int days = span.GetDays();
        span -= wxTimeSpan::Days(days);
        int hours = span.GetHours();
        span -= wxTimeSpan::Hours(hours);
        double minutes = (double)span.GetSeconds().ToLong()/60.0;
        span -= wxTimeSpan::Minutes(span.GetMinutes());
        int seconds = (double)span.GetSeconds().ToLong();
        
        timeStr = (days ? wxString::Format(_T("%dd "), days) : _T("")) +
        (hours || days ? wxString::Format(_T("%02d:%02d"), hours, (int)round(minutes)) :
         wxString::Format(_T("%02d %02d"), (int)floor(minutes), seconds));
    }
    else
    {
        timeStr = _("N/A");
    }
    return timeStr;
}


#ifdef __MINGW32__
char *strtok_r(char *str, const char *delim, char **save)
{
    char *res, *last;

    if( !save )
        return strtok(str, delim);
    if( !str && !(str = *save) )
        return NULL;
    last = str + strlen(str);
    if( (*save = res = strtok(str, delim)) )
    {
        *save += strlen(res);
        if( *save < last )
            (*save)++;
        else
            *save = NULL;
    }
    return res;
}
#endif
