/***********************************************************************************
* System Monitor: Plasmoid and data engines to monitor CPU/Memory/Swap Usage.
* Copyright (C) 2008  Matthew Dawson
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
***********************************************************************************/

#include "mem_usage.h"
#include <QFile>
#include <QTextStream>

MemMonitor::MemMonitor(QObject* parent, const QVariantList& args):
		Plasma::DataEngine(parent),
		meminfo(new QFile("/proc/meminfo")){

	Q_UNUSED(args)

	setMinimumPollingInterval(500);

	QTimer::singleShot(/*3*60000*/1000, this, SLOT(printUsage()));

}

MemMonitor::~MemMonitor(){

}

void MemMonitor::init(){

	///@todo:If solid can report this, switch to that.
	sourceRequestEvent("RAM");
	sourceRequestEvent("Swap");

}

bool MemMonitor::sourceRequestEvent(const QString &source){

	return updateSourceEvent(source);

}

bool MemMonitor::parseFile(QStringList fields, QMap<QString, int> &values){

	QTextStream readin;
	QString input;
	unsigned char found_strings = 0;

	if(meminfo->openMode() == QIODevice::NotOpen){

		if(!meminfo->open(QIODevice::ReadOnly | QIODevice::Text)){

			return false;

		}

	}

	readin.setDevice(meminfo);
	readin.seek(0);
	do{

		readin >> input;
		if(fields.contains(input, Qt::CaseInsensitive)){

//			do{
				readin >> values[input];
			++found_strings;

		}

	}while((found_strings < fields.count() && !readin.atEnd()));


	if(found_strings<fields.count()){

		return false;

	}

	return true;

}

bool MemMonitor::updateRAM(){

	QMap<QString, int> input;

	if( !parseFile((QStringList() << "MemTotal:" << "MemFree:" << "Buffers:" << "Cached:"), input)){

		return false;

	}

	double total_ram = input["MemTotal:"];

	setData("RAM", "Free", input["MemFree:"] / total_ram);
	setData("RAM", "Buffers", input["Buffers:"] / total_ram);
	setData("RAM", "Cached", input["Cached:"] / total_ram);
	setData("RAM", "Used", (input["MemTotal:"] - input["MemFree:"] - input["Buffers:"] - input["Cached:"]) / total_ram);

	setData("RAM", "rUsed", (int)(((input["MemTotal:"]*1000 - input["MemFree:"]*1000 ) * 5760 ) / (total_ram*1000)));

	setData("RAM", "iFree", (int)(input["MemFree:"]/1024) );
	setData("RAM", "iBuffers", (int)(input["Buffers:"]/1024) );
	setData("RAM", "iCached", (int)(input["Cached:"]/1024) );
	setData("RAM", "iUsed", (int)((input["MemTotal:"] - input["MemFree:"] - input["Buffers:"] - input["Cached:"])/1024) );
	setData("RAM", "iTotal", (int)(input["MemTotal:"]/1024) );

	return true;

}

bool MemMonitor::updateSwap(){

	QMap<QString, int> input;

	if( !parseFile((QStringList() << "SwapTotal:" << "SwapFree:"), input)){

		return false;

	}

	double total_swap = input["SwapTotal:"];

	setData("Swap", "Free", input["SwapFree:"] / total_swap);
	setData("Swap", "Used", (input["SwapTotal:"] - input["SwapFree:"]) / total_swap);

	setData("Swap", "rUsed", ((input["SwapTotal:"]*1000 - input["SwapFree:"]*1000) * 5760) / (total_swap*1000));

	setData("Swap", "iFree", (int)(input["SwapFree:"]/1024) );
	setData("Swap", "iUsed", (int)((input["SwapTotal:"] - input["SwapFree:"])/1024) );

	return true;

}

bool MemMonitor::updateSourceEvent(const QString& source){
	kDebug() << "pid" << getpid();

	if(source == "RAM"){

		return updateRAM();

	}else if(source == "Swap"){

		return updateSwap();

	}else{

		return false;

	}

}

void MemMonitor::printUsage() {
	kDebug() << "pid" << getpid();
}


#include "mem_usage.moc"
