#include "device/DeviceAssetDefinition.h"
#include "Cres.h"
#include "datatable/FieldFormat.h"
#include "expression/function/Functions.h"
#include "expression/DefaultReferenceResolver.h"

TableFormatPtr DeviceAssetDefinition::FORMAT = DeviceAssetDefinition::initFORMAT();

TableFormatPtr DeviceAssetDefinition::initFORMAT()
{
    TableFormatPtr tf =  TableFormatPtr(new TableFormat());
    tf->setUnresizable(true);

    tf->addField("<" + FIELD_ID() + "><S><F=HRK>");
    tf->addField("<" + FIELD_DESCRIPTION() + "><S><F=R><D=" + Cres::get()->getString("description") + ">");
    tf->addField("<" + FIELD_ENABLED() + "><B><A=1><D=" + Cres::get()->getString("enabled") + ">");

    tf->addField(FieldFormat::create("<" + FIELD_CHILDREN() + "><T><F=N><D=" + Cres::get()->getString("devNestedAssets") + ">"));

    tf->setNamingExpression(Functions::AGGREGATE + "({}, \"{env/previous} + ({" + FIELD_ENABLED() + "} ? 1 : 0)\", 0) + '/' + {#" + DefaultReferenceResolver::RECORDS() + "}");

    AgString ref = FIELD_CHILDREN() + "#" + DataTableBindingProvider::PROPERTY_ENABLED();
    AgString exp = "{" + FIELD_ENABLED() + "}";
    tf->addBinding(ref, exp);
    return tf;
}

DeviceAssetDefinition::DeviceAssetDefinition():AggreGateBean(FORMAT)
{   
    this->enabled = false;
}

DeviceAssetDefinition::DeviceAssetDefinition(DataRecordPtr data):AggreGateBean(FORMAT, data)
{  
    this->enabled = false;
}

DeviceAssetDefinition::DeviceAssetDefinition(const AgString& id, const AgString& description):AggreGateBean(FORMAT)
{  
    this->enabled = false;
    this->id = id;
    this->description = description;
}


AgString DeviceAssetDefinition::getId()
{
    return id;
}

void DeviceAssetDefinition::setId(const AgString& id)
{
    this->id = id;
}

AgString DeviceAssetDefinition::getDescription()
{
    return description;
}

void DeviceAssetDefinition::setDescription(const AgString& description)
{
    this->description = description;
}

bool DeviceAssetDefinition::isEnabled()
{
    return enabled;
}

void DeviceAssetDefinition::setEnabled(bool enabled)
{
    this->enabled = enabled;
}

std::list<DeviceAssetDefinitionPtr> DeviceAssetDefinition::getChildren()
{
    return children;
}

void DeviceAssetDefinition::setChildren(std::list<DeviceAssetDefinitionPtr>  children)
{
  this->children = children;
}

void DeviceAssetDefinition::addSubgroup(DeviceAssetDefinitionPtr child)
{
   getChildren().push_back(child);
}

int DeviceAssetDefinition::compareTo(Comparable *other)
{
    UNUSED(other);
    return 0;    
}

AgString DeviceAssetDefinition::toString()
{
    AgString ss;
    ss = "GroupDefinition [id=" + id  + ", description=" + description + ", enabled=" + AgString::fromInt(enabled) +
       ", children=" + AgString::fromInt(children.size()) + "]";

    return ss;
}

int DeviceAssetDefinition::hashCode()
{
    const int prime = 31;
    int result = 1;                                               //todo - How to calculate a string hashCode?
    result = prime * result + ((description.empty() == true) ? 0 : 0xFFF/*description.hashCode()*/);
    return result;
}

bool DeviceAssetDefinition::equals(DeviceAssetDefinitionPtr obj)
{
    UNUSED(obj);
//todo
//	if (this == obj)
//		return true;
//
//	if (obj == NULL)
//		return false;
//
//	DeviceAssetDefinitionPtr other = (DeviceAssetDefinitionPtr)(obj);
//	if (other == NULL)
//		return false;
//
//	if (other->description != description)
//		return false;

    return true;
}
