// object.cpp - GUIObject base class

#include <stdio.h>
#include <stdlib.h>

#include <string>

extern "C" {
#include "../twcommon.h"
#include "../variables.h"
}

#include "rapidxml.hpp"
#include "objects.hpp"
#include "../data.hpp"

GUIObject::GUIObject(xml_node<>* node)
{
	mConditionsResult = true;
	if (node)
		LoadConditions(node, mConditions);
}

void GUIObject::LoadConditions(xml_node<>* node, std::vector<Condition>& conditions)
{
	xml_node<>* condition = FindNode(node, "conditions");
	if (condition)  condition = FindNode(condition, "condition");
	else			condition = FindNode(node, "condition");

	while (condition)
	{
		Condition cond;

		cond.mCompareOp = "=";

		xml_attribute<>* attr;
		attr = condition->first_attribute("var1");
		if (attr)   cond.mVar1 = attr->value();

		attr = condition->first_attribute("op");
		if (attr)   cond.mCompareOp = attr->value();

		attr = condition->first_attribute("var2");
		if (attr)   cond.mVar2 = attr->value();

		conditions.push_back(cond);

		condition = condition->next_sibling("condition");
	}
}

GUIObject::~GUIObject()
{
}

bool GUIObject::IsConditionVariable(std::string var)
{
	std::vector<Condition>::iterator iter;
	for (iter = mConditions.begin(); iter != mConditions.end(); iter++)
	{
		if (iter->mVar1 == var)
			return true;
	}
	return false;
}

bool GUIObject::isConditionTrue()
{
	return mConditionsResult;
}

bool GUIObject::isConditionTrue(Condition* condition)
{
	// This is used to hold the proper value of "true" based on the '!' NOT flag
	bool bTrue = true;

	if (condition->mVar1.empty())
		return bTrue;

	if (!condition->mCompareOp.empty() && condition->mCompareOp[0] == '!')
		bTrue = false;

	if (condition->mVar2.empty() && condition->mCompareOp != "modified")
	{
		if (!DataManager::GetStrValue(condition->mVar1).empty())
			return bTrue;

		return !bTrue;
	}

	string var1, var2;
	if (DataManager::GetValue(condition->mVar1, var1))
		var1 = condition->mVar1;
	if (DataManager::GetValue(condition->mVar2, var2))
		var2 = condition->mVar2;

	// This is a special case, we stat the file and that determines our result
	if (var1 == "fileexists")
	{
		struct stat st;
		if (stat(var2.c_str(), &st) == 0)
			var2 = var1;
		else
			var2 = "FAILED";
	}
	if (var1 == "mounted")
	{
		if (isMounted(condition->mVar2))
			var2 = var1;
		else
			var2 = "FAILED";
	}

	if (condition->mCompareOp.find('=') != string::npos && var1 == var2)
		return bTrue;

	if (condition->mCompareOp.find('>') != string::npos && (atof(var1.c_str()) > atof(var2.c_str())))
		return bTrue;

	if (condition->mCompareOp.find('<') != string::npos && (atof(var1.c_str()) < atof(var2.c_str())))
		return bTrue;

	if (condition->mCompareOp == "modified")
	{
		// This is a hack to allow areas to reset the default value
		if (var1.empty())
		{
			condition->mLastVal = var1;
			return !bTrue;
		}

		if (var1 != condition->mLastVal)
			return bTrue;
	}

	return !bTrue;
}

bool GUIObject::isConditionValid()
{
	return !mConditions.empty();
}

int GUIObject::NotifyVarChange(const std::string& varName, const std::string& value __unused)
{
	mConditionsResult = UpdateConditions(mConditions, varName);
	return 0;
}

bool GUIObject::UpdateConditions(std::vector<Condition>& conditions, const std::string& varName)
{
	bool result = true;

	const bool varNameEmpty = varName.empty();
	std::vector<Condition>::iterator iter;
	for (iter = conditions.begin(); iter != conditions.end(); ++iter)
	{
		if(varNameEmpty && iter->mCompareOp == "modified")
		{
			string val;

			// If this fails, val will not be set, which is perfect
			if (DataManager::GetValue(iter->mVar1, val))
			{
				DataManager::SetValue(iter->mVar1, "");
				DataManager::GetValue(iter->mVar1, val);
			}
			iter->mLastVal = val;
		}

		if(varNameEmpty || iter->mVar1 == varName || iter->mVar2 == varName)
			iter->mLastResult = isConditionTrue(&(*iter));

		if(!iter->mLastResult)
			result = false;
	}
	return result;
}

bool GUIObject::isMounted(string vol)
{
	FILE *fp;
	char tmpOutput[255];

	fp = fopen("/proc/mounts", "rt");
	while (fgets(tmpOutput,255,fp) != NULL)
	{
		char* mnt = tmpOutput;
		while (*mnt > 32)			mnt++;
		while (*mnt > 0 && *mnt <= 32)	mnt++;
		char* pos = mnt;
		while (*pos > 32)   pos++;
		*pos = 0;
		if (vol == mnt)
		{
			fclose(fp);
			return true;
		}
	}
	fclose(fp);
	return false;
}
