#include "context/FunctionDefinition.h"
#include "datatable/TableFormat.h"
#include "context/FunctionImplementation.h"
#include "security/Permissions.h"

FunctionDefinition::FunctionDefinition(const AgString &name, TableFormatPtr inputFormat, TableFormatPtr outputFormat)
{
    init(name, inputFormat, outputFormat, AgString(), AgString());
}

FunctionDefinition::FunctionDefinition(const AgString &name, TableFormatPtr inputFormat, TableFormatPtr outputFormat,  const AgString &description)
{
    init(name, inputFormat, outputFormat, description, AgString());
}

FunctionDefinition::FunctionDefinition(const AgString &name, TableFormatPtr inputFormat, TableFormatPtr outputFormat, const AgString &description, const AgString &group)
{
    init(name, inputFormat, outputFormat, description, group);
}

void FunctionDefinition::init(const AgString &name, TableFormatPtr inputFormat, TableFormatPtr outputFormat, const AgString &description, const AgString &group)
{
    hidden = false;
    concurrent = false;

    setName(name);

    setInputFormat(inputFormat);
    setOutputFormat(outputFormat);

    setDescription(description);
    setGroup(group);
}

TableFormatPtr FunctionDefinition::getInputFormat()
{
    return inputFormat;
}

TableFormatPtr FunctionDefinition::getOutputFormat()
{
    return outputFormat;
}

bool FunctionDefinition::isHidden()
{
    return hidden;
}

PermissionsPtr FunctionDefinition::getPermissions()
{
    return permissions;
}

FunctionImplementationPtr FunctionDefinition::getImplementation()
{
    return implementation;
}

void FunctionDefinition::setInputFormat(TableFormatPtr inputFormat)
{
	if(inputFormat != 0)
	{
        inputFormat->makeImmutable(NULL);
	}
	this->inputFormat = inputFormat;
}

void FunctionDefinition::setOutputFormat(TableFormatPtr outputFormat)
{
	if(outputFormat != 0)
	{
        outputFormat->makeImmutable(NULL);
    }
    this->outputFormat = outputFormat;
}

void FunctionDefinition::setHidden(bool hidden)
{
    this->hidden = hidden;
}

void FunctionDefinition::setPermissions(PermissionsPtr perms)
{
    this->permissions = perms;
}

bool FunctionDefinition::isConcurrent()
{
    return concurrent;
}

void FunctionDefinition::setConcurrent(bool concurrent)
{
    this->concurrent = concurrent;
}

void FunctionDefinition::setImplementation(FunctionImplementationPtr implementation)
{
    this->implementation = implementation;
}

Cloneable *FunctionDefinition::clone()
{
    //todo
    assert(0);
    return 0;
}

int FunctionDefinition::compareTo(Comparable* /*def*/)
{
    //todo
    assert(0);
    /*if (getIndex() != null || d.getIndex() != null)
    {
        Integer my = getIndex() != null ? getIndex() : new Integer(0);
        Integer other = d.getIndex() != null ? d.getIndex() : new Integer(0);
        return other.compareTo(my);
    }*/

    return 0;
}


int FunctionDefinition::hashCode()
{
    //const int prime = 31;
    int result = 1;
    assert(0);
    /*
    result = prime * result + ((getDescription() == 0) ? int(0) : getDescription())->hashCode());
    result = prime * result + ((getGroup() == 0) ? int(0) : getGroup())->hashCode());
    result = prime * result + ((getHelp() == 0) ? int(0) : getHelp())->hashCode());
    result = prime * result + (hidden ? int(1231) : int(1237));
    result = prime * result + ((getIndex() == 0) ? int(0) : getIndex())->hashCode());
    result = prime * result + ((inputFormat == 0) ? int(0) : inputFormat)->hashCode());
    result = prime * result + ((getName() == 0) ? int(0) : getName())->hashCode());
    result = prime * result + ((outputFormat == 0) ? int(0) : outputFormat)->hashCode());
    result = prime * result + ((implementation == 0) ? int(0) : implementation)->hashCode());
    result = prime * result + ((permissions == 0) ? int(0) : permissions)->hashCode());
	*/
    return result;
}

bool FunctionDefinition::equals(FunctionDefinition *other)
{    
    if (this == other) {
        return true;
    }

    if (other == NULL) {
        return false;
    }

    if (getDescription() != other->getDescription()) {
        return false;
    }

    if (getGroup() != other->getGroup()) {
        return false;
    }

    if (getHelp() != other->getHelp()) {
        return false;
    }

    if (hidden != other->hidden) {
        return false;
    }

    if (getIndex() != other->getIndex()) {
        return false;
    }

    if (inputFormat == NULL) {
        if (other->inputFormat != NULL) {
            return false;
        }
    }else if (!inputFormat->equals(other->inputFormat.get())) {
        return false;
    }

    if (getName() != other->getName()) {
        return false;
    }

    if (outputFormat == NULL) {
        if (other->outputFormat != NULL) {
            return false;
        }
    }
    else if (!outputFormat->equals(other->outputFormat.get())) {
        return false;
    }

    if (implementation == NULL) {
        if (other->implementation != NULL) {
            return false;
        }
    }else if (!implementation->equals(other->implementation.get())) {
        return false;
    }

    if (permissions == NULL) {
        if (other->permissions != NULL) {
            return false;
        }
    }else if (!permissions->equals(other->permissions.get())) {
        return false;
    }

    return true;
}



