#include "OTAManager.h"
#include "definition.h"

#define DEBUG_OTA_MANAGER(...) do {} while(0)
//#define DEBUG_OTA_MANAGER(...) do { Serial.printf(__VA_ARGS__); Serial.println();} while(0)

OTAManager::OTAManager(SDCardManager &sdCardManager, const BoardConfig &boardConfig) : _sdCardManager(&sdCardManager), _boardConfig(&boardConfig)
{ }

OTAManager::~OTAManager()
{ }

boolean OTAManager::init(void)
{    
    //We try to read the config file
    CFGDictionary<CFGParameterValue> *otaCfg = _sdCardManager->getCFGFile(OTA_CFG_FILE);
    boolean toReturn(true);
    //If we did not find the file or we didn't manage to open it !
    if(!otaCfg)
    {
        DEBUG_OTA_MANAGER("otaCfg is NULL !");
        return false;
    }   

    if((*otaCfg)("ENABLED") != nullptr)
    {
        if((*otaCfg)("ENABLED")->booleanValue())
        {
            DEBUG_OTA_MANAGER("ENABLED : %s", (*otaCfg)("ENABLED")->stringValue());
            if((*otaCfg)("OTA_SERVER_ADDRESS") != nullptr) //This is the only required parameter
            {
                _isServiceEnabled = true;
                _otaUpdater.setLedPin(_boardConfig->getOnBoard_LED(), LOW);
                _otaUpdater.onStart(std::bind(&OTAManager::updateStartedCb, this));
                _otaUpdater.onError(std::bind(&OTAManager::updateErrorCb, this, std::placeholders::_1));
                _otaUpdater.onProgress(std::bind(&OTAManager::updateProgressdCb, this, std::placeholders::_1, std::placeholders::_2));
                _otaUpdater.onEnd(std::bind(&OTAManager::updateFinishedCb, this));


                _otaUpdater.setServerAddress((*otaCfg)("OTA_SERVER_ADDRESS")->stringValue());
                
                if((*otaCfg)("OTA_SERVER_PORT") != nullptr)
                {
                    DEBUG_OTA_MANAGER("OTA_SERVER_PORT : %s", (*otaCfg)("OTA_SERVER_PORT")->stringValue());
                    _otaUpdater.setPort((*otaCfg)("OTA_SERVER_PORT")->uintValue());
                }
                    
                if((*otaCfg)("OTA_SERVICE_PATH") != nullptr)
                {
                    DEBUG_OTA_MANAGER("OTA_SERVICE_PATH : %s", (*otaCfg)("OTA_SERVICE_PATH")->stringValue());
                    _otaUpdater.setPath((*otaCfg)("OTA_SERVICE_PATH")->stringValue());
                }
                
                if((*otaCfg)("OTA_SERVICE_AUTH_KEY") != nullptr)
                {
                    DEBUG_OTA_MANAGER("OTA_SERVICE_AUTH_KEY : %s", (*otaCfg)("OTA_SERVICE_AUTH_KEY")->stringValue());
                    _otaUpdater.setOtaAuthKey((*otaCfg)("OTA_SERVICE_AUTH_KEY")->stringValue());
                }
            }
            else
            {
                DEBUG_OTA_MANAGER("OTA_SERVER_ADDRESS is NULL !");
                _isServiceEnabled = false;
                toReturn = false;
            }
        }
        else
            _isServiceEnabled = false;
    }
    else
    {
        DEBUG_OTA_MANAGER("ENABLED is NULL !");
        _isServiceEnabled = false;
        toReturn = false;
    }
        
    delete otaCfg;

    return toReturn;
}

boolean OTAManager::isEnabled(void) const
{
    return _isServiceEnabled;
}

OTAUpdater& OTAManager::getOTAUpdater(void)
{
    return _otaUpdater;
}

void OTAManager::updateStartedCb(void)
{
    Serial.println("CALLBACK:  HTTP update process started");
}

void OTAManager::updateFinishedCb(void)
{
    Serial.println("CALLBACK:  HTTP update process finished");
}

void OTAManager::updateProgressdCb(int cur, int total)
{
    Serial.printf("CALLBACK:  HTTP update process at %d of %d bytes...\n", cur, total);
}

void OTAManager::updateErrorCb(int err)
{
    Serial.printf("CALLBACK:  HTTP update fatal error code %d\n", err);
}
