/**
* Lubricant Detecter
* Copyright (C) 2021 Carl Klemm
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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 "log.h"
#include "smtp/smtp.h"

Log::Log()
{
	mutex.lock();
}

Log::Log(Level type, bool endlineI, bool timeI): endline(endlineI), time(timeI)
{
	mutex.lock();
	msglevel = type;
	if(headers) 
	{
		operator << ("["+getLabel(type)+"] ");
	}
}

Log::~Log() 
{
	if(opened)
	{
		bool ret;
		if(endline)
		{
			std::cout<<std::endl;
			buffer<<'\n';
		}
		std::string mailbody = buffer.str();

		if(sendmailEnabled && msglevel >= sendmailLevel)
		{
			sendmailEnabled = false;
			ret = sendmail("Coincell Expirament", mailbody);
			if(!ret)
				Log(WARN)<<"Unable to send message to "<<reportingAddr;
			sendmailEnabled = true;
		}
	}
	opened = false;
	mutex.unlock();
}

std::string Log::getLabel(Level level) 
{
	std::string label;
	switch(level) 
	{
		case DEBUG: 
			label = "DEBUG"; 
			break;
		case INFO:  
			label = "INFO "; 
			break;
		case WARN:  
			label = "WARN "; 
			break;
		case ERROR: 
			label = "ERROR"; 
			break;
	}
	return label;
}

void Log::setupSendmail(std::string serverIn, std::string portIn, std::string usernameIn,
						std::string passwordIn, std::string fromNameIn, std::string reportingAddrIn)
{
	server = serverIn;
	port = portIn;
	username = usernameIn;
	password = passwordIn;
	fromName = fromNameIn;
	reportingAddr = reportingAddrIn;
	sendmailEnabled = true;
}

bool Log::sendmail(const std::string& subj, const std::string& body)
{
	smtp* mailer;
	smtp_status_code ret = smtp_open(server.c_str(), port.c_str(),
									 SMTP_SECURITY_TLS, SMTP_NO_CERT_VERIFY, NULL, &mailer);
	if(ret != SMTP_STATUS_OK)
	{
		Log(Log::ERROR)<<"Mailer unable open "<<server<<" returns "<<ret;
		return false;
	}

	ret = smtp_auth(mailer, SMTP_AUTH_PLAIN, username.c_str(), password.c_str());
	if(ret != SMTP_STATUS_OK)
	{
		smtp_close(mailer);
		Log(Log::ERROR)<<"Mailer unable auth with "<<server<<" smtp returns "<<ret;
		return false;
	}

	ret = smtp_address_add(mailer, SMTP_ADDRESS_FROM,  username.c_str(), fromName.c_str());
	if(ret != SMTP_STATUS_OK)
	{
		smtp_close(mailer);
		Log(Log::ERROR)<<"Mailer unable add address "<<ret;
		return false;
	}

	ret = smtp_address_add(mailer, SMTP_ADDRESS_TO, reportingAddr.c_str(), NULL);
	if(ret != SMTP_STATUS_OK)
	{
		smtp_close(mailer);
		Log(Log::ERROR)<<"Mailer unable add address "<<ret;
		return false;
	}

	ret = smtp_header_add(mailer, "Subject", subj.c_str());
	if(ret != SMTP_STATUS_OK)
	{
		smtp_close(mailer);
		Log(Log::ERROR)<<"Mailer unable add subject "<<ret;
		return false;
	}

	ret = smtp_mail(mailer, body.c_str());
	if(ret != SMTP_STATUS_OK)
	{
		smtp_close(mailer);
		Log(Log::ERROR)<<"Mailer unable send mail "<<ret;
		return false;
	}

	return true;
}

bool Log::headers = false;
Log::Level Log::level = WARN;
Log::Level Log::sendmailLevel = WARN;

bool Log::sendmailEnabled = false;
std::stringstream Log::buffer;
std::string Log::server;
std::string Log::port;
std::string Log::username;
std::string Log::password;
std::string Log::fromName;
std::string Log::reportingAddr;
std::mutex Log::mutex;