/**********************************************************************************************
    Copyright (C) 2007 Oliver Eichler oliver.eichler@gmx.de

    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 USA

  Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd.
  or one of its subsidiaries.

**********************************************************************************************/

#include "config.h"
#include "IDeviceDefault.h"

#include <iostream>

using namespace Garmin;
using namespace std;

IDeviceDefault::IDeviceDefault()
{
    pthread_mutex_init(&mutex, NULL);
}


IDeviceDefault::~IDeviceDefault()
{

}


void IDeviceDefault::callback(int progress, int * ok, int * cancel, const char * title, const char * msg)
{
    if(_callback_) {
        _callback_(progress,ok,cancel,title,msg,_self_);
    }
}


void IDeviceDefault::setPort(const char * p)
{
    port = p;
}


void IDeviceDefault::uploadMap(const uint8_t * mapdata, uint32_t size, const char * key)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _uploadMap(mapdata, size, key);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to upload maps. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::uploadMap(const char * filename, uint32_t size, const char * key)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _uploadMap(filename, size, key);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to upload maps. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::queryMap(std::list<Map_t>& maps)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _queryMap(maps);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to query loaded maps. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::downloadWaypoints(std::list<Garmin::Wpt_t>& waypoints)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _downloadWaypoints(waypoints);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to download waypoints. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::uploadWaypoints(std::list<Garmin::Wpt_t>& waypoints)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _uploadWaypoints(waypoints);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to upload waypoints. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::downloadTracks(std::list<Garmin::Track_t>& tracks)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _downloadTracks(tracks);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to download tracks. " + e.msg;
        throw (int)e.err;
    }

}


void IDeviceDefault::uploadTracks(std::list<Garmin::Track_t>& tracks)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _uploadTracks(tracks);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to upload tracks. " + e.msg;
        throw (int)e.err;
    }

}


void IDeviceDefault::uploadRoutes(std::list<Garmin::Route_t>& routes)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _uploadRoutes(routes);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to upload routes. " + e.msg;
        throw (int)e.err;
    }

}


void IDeviceDefault::downloadRoutes(std::list<Garmin::Route_t>& routes)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _downloadRoutes(routes);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to download routes. " + e.msg;
        throw (int)e.err;
    }

}


void IDeviceDefault::uploadCustomIcons(std::list<Garmin::Icon_t>& icons)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _uploadCustomIcons(icons);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to upload icons. " + e.msg;
        throw (int)e.err;
    }

}


void IDeviceDefault::screenshot(char *& clrtbl, char *& data, int& width, int& height)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _screenshot(clrtbl, data, width, height);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to download screenshot. " + e.msg;
        throw (int)e.err;
    }

}


void IDeviceDefault::setRealTimeMode(bool on)
{
    lasterror = "";
    try
    {
        _setRealTimeMode(on);
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to change real time mode. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::getRealTimePos(Garmin::Pvt_t& pvt)
{
    // don't reset last error because it might hold the reason,
    // why the realtime thread died.
    //lasterror = "";
    try
    {
        _getRealTimePos(pvt);
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to request real time position. " + e.msg;
        throw (int)e.err;
    }
}


void IDeviceDefault::getDevProperties(Garmin::DevProperties_t& dev_properties)
{
    lasterror = "";
    try
    {
        CMutexLocker lock(mutex);
        _acquire();
        _getDevProperties(dev_properties);
        _release();
    }
    catch(exce_t& e) {
        if(e.err != errBlocked) _release();
        lasterror = "Failed to obtain GPS properties. " + e.msg;
        throw (int)e.err;
    }
}


const std::string& IDeviceDefault::getCopyright()
{
    return copyright;
}


const std::string& IDeviceDefault::getLastError()
{
    return lasterror;
}


void IDeviceDefault::_uploadMap(const uint8_t * , uint32_t , const char * )
{
    throw exce_t(errNotImpl,"uploadMap(): this method is not implemented for your device.");
}


void IDeviceDefault::_uploadMap(const char * , uint32_t , const char * )
{
    throw exce_t(errNotImpl,"uploadMap(): this method is not implemented for your device.");
}


void IDeviceDefault::_queryMap(std::list<Map_t>& )
{
    throw exce_t(errNotImpl,"queryMap(): this method is not implemented for your device.");
}


void IDeviceDefault::_downloadWaypoints(std::list<Garmin::Wpt_t>& )
{
    throw exce_t(errNotImpl,"downloadWaypoints(): this method is not implemented for your device.");
}


void IDeviceDefault::_uploadWaypoints(std::list<Garmin::Wpt_t>& )
{
    throw exce_t(errNotImpl,"uploadWaypoints(): this method is not implemented for your device.");
}


void IDeviceDefault::_downloadTracks(std::list<Garmin::Track_t>& )
{
    throw exce_t(errNotImpl,"downloadTracks(): this method is not implemented for your device.");
}


void IDeviceDefault::_uploadTracks(std::list<Garmin::Track_t>& )
{
    throw exce_t(errNotImpl,"uploadTracks(): this method is not implemented for your device.");
}


void IDeviceDefault::_downloadRoutes(std::list<Garmin::Route_t>& )
{
    throw exce_t(errNotImpl,"downloadRoutes(): this method is not implemented for your device.");
}


void IDeviceDefault::_uploadRoutes(std::list<Garmin::Route_t>& )
{
    throw exce_t(errNotImpl,"uploadRoutes(): this method is not implemented for your device.");
}


void IDeviceDefault::_uploadCustomIcons(std::list<Garmin::Icon_t>& )
{
    throw exce_t(errNotImpl,"uploadCustomIcons(): this method is not implemented for your device.");
}


void IDeviceDefault::_screenshot(char *& /*clrtbl*/, char *& /*data*/, int& /*width*/, int& /*height*/)
{
    throw exce_t(errNotImpl,"screenshot(): this method is not implemented for your device.");
}


void IDeviceDefault::_setRealTimeMode(bool)
{
    throw exce_t(errNotImpl,"setRealTimeMode(): this method is not implemented for your device.");
}


void IDeviceDefault::_getRealTimePos(Garmin::Pvt_t&)
{
    throw exce_t(errNotImpl,"getRealTimePos(): this method is not implemented for your device.");
}


void IDeviceDefault::_getDevProperties(Garmin::DevProperties_t& dev_properties)
{
    // mark all properties as not having been set to meaningful values
    properties.set.all = (uint32_t) 0;

    // return a copy of the device properties block
    dev_properties = properties;
}
