#include "LogicGateNode.h"

#include "Path.h"
#include "PathNode.h"
#include "CircleNode.h"

#include "LogicGate.h"
#include "LogicGatePrimitiveShapes.h"

LogicGateNode::LogicGateNode(const Transform& transform)
    : CircuitElementNode(transform)
{

}

LogicGateNode::~LogicGateNode()
{

}

Point LogicGateNode::getConnectionLocation(Wire* wire) const
{
    bool is_input{ false };
    std::size_t connection_id{ 0 };

    for (std::size_t idx = 0; idx < mContent->getNumInputs(); idx++)
    {
        if (mContent->getInput(idx) == wire)
        {
            is_input = true;
            connection_id = idx;
            break;
        }
    }

    for (std::size_t idx = 0; idx < mContent->getNumOutputs(); idx++)
    {
        if (mContent->getOutput(idx) == wire)
        {
            connection_id = idx;
            break;
        }
    }

    Point loc;
    if (mContent->getGateType() == LogicGate::GateType::AND)
    {
        loc = LogicGatePrimitiveShapes::getAndGateConnectionLocation(is_input, connection_id);
    }
    else if (mContent->getGateType() == LogicGate::GateType::OR)
    {
        loc = LogicGatePrimitiveShapes::getOrGateConnectionLocation(is_input, connection_id);
    }

    loc.move(mTransform.getLocation().getX(), mTransform.getLocation().getY());
    return loc;

}

void LogicGateNode::setContent(LogicGate* content)
{
    mContent = content;
    mContentDirty = true;
}

void LogicGateNode::update(SceneInfo* sceneInfo)
{
    if (mContentDirty)
    {
        createOrUpdateGeometry(sceneInfo);
        mContentDirty = false;
    }
}

void LogicGateNode::createOrUpdateGeometry(SceneInfo*)
{
    if (!mPrimaryPath)
    {
        if (mContent->getGateType() == LogicGate::GateType::AND)
        {
            mPrimaryPath = std::make_unique<PathNode>(Transform(), LogicGatePrimitiveShapes::getAndGateShape());
        }
        else if (mContent->getGateType() == LogicGate::GateType::OR)
        {
            mPrimaryPath = std::make_unique<PathNode>(Transform(), LogicGatePrimitiveShapes::getOrGateShape());
        }

        if (mPrimaryPath)
        {
            addChild(mPrimaryPath.get());
        }
    }
}
