#include"TcPch.h"
#pragma hdrstop
#include"Simulator.h"
#if defined( _DEBUG ) && defined(_WITH_SIMULATOR)
#include"CRemoteLog.h"
#define FLOAT_ZERO 0.0001
Simulator::Simulator() {
	length = 0;
	for (int i = 0; i < MAX_CONDITION_COUNT; i++) {
		for (int j = 0; j < MAX_CONDITION_ITEM_COUNT; j++) {
			data[i][j].attr = NULL;
			data[i][j].elapsedTime = 0;
			data[i][j].index = i;
			data[i][j].offset = j;
			data[i][j].op = SMOP::NONE;
			data[i][j].value.DoubleValue = 0;
			if (j == MAX_CONDITION_ITEM_COUNT - 1) {
				data[i][j].next = NULL;
			}
			else {
				data[i][j].next = &data[i][j + 1];
			}
		}
	}
}
ConditionNode* ConditionNode::when(DeviceAttribute* attr, SMOP op, bool value)
{	
	
	this->next->attr = attr;
	this->next->op = op;
	this->next->value.BoolValue = value;
	return this->next;
}

ConditionNode* ConditionNode::when(DeviceAttribute* attr, SMOP op, double value)
{
	this->next->attr = attr;
	this->next->op = op;
	this->next->value.DoubleValue = value;
	return this->next;
}

ConditionNode* ConditionNode::wait(long value)
{
	this->next->attr = NULL;
	this->next->op = SMOP::WAIT;
	this->next->value.LongValue = value;
	return this->next;
}

ConditionNode* ConditionNode::set(DeviceAttribute* attr, double value)
{
	this->next->attr = attr;
	this->next->op = SMOP::SET;
	this->next->value.BoolValue = value;
	return this->next;
}

ConditionNode* ConditionNode::set(DeviceAttribute* attr, bool value)
{
	this->next->attr = attr;
	this->next->op = SMOP::SET;
	this->next->value.BoolValue = value;
	return this->next;
}


ConditionNode* Simulator::when(DeviceAttribute* attr, SMOP op, bool value)
{

	data[length]->attr = attr;
	data[length]->op = op;
	data[length]->value.BoolValue = value;
	return data[length++];
}

ConditionNode* Simulator::when(DeviceAttribute* attr, SMOP op, double value)
{
	data[length]->attr = attr;
	data[length]->op = op;
	data[length]->value.DoubleValue = value;
	return data[length++];
}

ConditionNode* Simulator::wait(long value)
{
	data[length]->attr = NULL;
	data[length]->op = SMOP::WAIT;
	data[length]->value.LongValue = value;
	return data[length++];
}

ConditionNode* Simulator::set(DeviceAttribute* attr, double value)
{
	data[length]->attr = attr;
	data[length]->op = SMOP::SET;
	data[length]->value.DoubleValue = value;
	return data[length++];
}
ConditionNode* Simulator::set(DeviceAttribute* attr, bool value)
{
	data[length]->attr = attr;
	data[length]->op = SMOP::SET;
	data[length]->value.BoolValue = value;
	return data[length++];
}
const char* novar_text = "Simulator error : undefine attribute in %s condition";
void Simulator::monitor()
{
	for (int i = 0; i < length; i++) {
		int j = 0;
		for(j=0;j<MAX_CONDITION_ITEM_COUNT;j++){
			ConditionNode* node = &data[i][j];
			if (node->op == SMOP::NONE) {
				break;
			}else if (node->op == SMOP::EQ) {
				if (node->attr == NULL) {
					logger->error(novar_text,"EQ");
					return;
				}
				bool checkResult = false;
				if (node->attr->type == ATTR_TYPE_BOOL){
					checkResult = node->attr->getBoolValue() == node->value.BoolValue;
				}
				else {
					double corr = node->attr->getDoubleValue() - node->value.DoubleValue;
					checkResult = corr >= -FLOAT_ZERO && corr <= FLOAT_ZERO;
				}
				if (!checkResult) {
					break;
				}
			}
			else if (node->op == SMOP::NE) {
				if (node->attr == NULL) {
					logger->error(novar_text, "NE");
					return;
				}
				bool checkResult = false;
				if (node->attr->type == ATTR_TYPE_BOOL) {
					checkResult = node->attr->getBoolValue() != node->value.BoolValue;
				}
				else {
					double corr = node->attr->getDoubleValue() - node->value.DoubleValue;
					checkResult = corr >= -FLOAT_ZERO && corr != FLOAT_ZERO;
				}
				if (!checkResult) {
					break;
				}
			}
			else if (node->op == SMOP::GT) {
				if (node->attr == NULL) {
					logger->error(novar_text,"GT");
					return;
				}
				bool checkResult = false;
				if (node->attr->type == ATTR_TYPE_BOOL) {
					checkResult = node->attr->getBoolValue() > node->value.BoolValue;
				}
				else {
					double corr = node->attr->getDoubleValue() - node->value.DoubleValue;
					checkResult = corr >=FLOAT_ZERO;
				}
				if (!checkResult) {
					break;
				}
			}
			else if (node->op == SMOP::GE) {
				if (node->attr == NULL) {
					logger->error(novar_text,"GE");
					return;
				}
				bool checkResult = false;
				if (node->attr->type == ATTR_TYPE_BOOL) {
					checkResult = node->attr->getBoolValue() >= node->value.BoolValue;
				}
				else {
					double corr = node->attr->getDoubleValue() - node->value.DoubleValue;
					checkResult = corr >= -FLOAT_ZERO;
				}
				if (!checkResult) {
					break;
				}
			}
			else if (node->op == SMOP::LT) {
				if (node->attr == NULL) {
					logger->error(novar_text,"LT");
					return;
				}
				bool checkResult = false;
				if (node->attr->type == ATTR_TYPE_BOOL) {
					checkResult = node->attr->getBoolValue() <= node->value.BoolValue;
				}
				else {
					double corr = node->attr->getDoubleValue() - node->value.DoubleValue;
					checkResult = corr <= -FLOAT_ZERO;
				}
				if (!checkResult) {
					break;
				}
			}
			else if (node->op == SMOP::LE) {
				if (node->attr == NULL) {
					logger->error(novar_text,"LE");
					return;
				}
				bool checkResult = false;
				if (node->attr->type == ATTR_TYPE_BOOL) {
					checkResult = node->attr->getBoolValue() <= node->value.BoolValue;
				}
				else {
					double corr = node->attr->getDoubleValue() - node->value.DoubleValue;
					checkResult = corr <= FLOAT_ZERO;
				}
				if (!checkResult) {
					break;
				}
			}
			else if (node->op == SMOP::WAIT) {
				node->elapsedTime += TASK_TM;
				bool checkResult = node->elapsedTime >= node->value.LongValue;
				
				if (!checkResult) {
					break;
				}
				node->elapsedTime = node->value.LongValue;
			}
			else if (node->op == SMOP::SET) {
				if (node->attr == NULL) {
					logger->error(novar_text,"SET");
					return;
				}
				
				if (node->attr->type == ATTR_TYPE_BOOL) {
					node->attr->setBoolValue(node->value.BoolValue);
				}
				else {
					node->attr->setDoubleValue(node->value.DoubleValue);
				}
				
			}
			if (data[i][j].op == SMOP::NONE) {
				for (int k = 0; k < j; k++) {
					data[i][k].elapsedTime = 0;
				}
			}

		}
	}
}

#endif