#include "QuantumGate.h"

NInMOutQuantumGate::NInMOutQuantumGate(std::size_t numIn, std::size_t numOut, std::vector<AbstractQuantumWire*> inputs, std::vector<AbstractQuantumWire*> outputs)
    : QuantumGate(),
    mNumIn(numIn),
    mNumOut(numOut)
{
    if (inputs.size() == mNumIn)
    {
        mInputs = inputs;
    }
    else
    {
        mInputs = std::vector<AbstractQuantumWire*>(numIn, nullptr);
    }

    if (outputs.size() == mNumOut)
    {
        mOutputs = outputs;
    }
    else
    {
        mOutputs = std::vector<AbstractQuantumWire*>(numOut, nullptr);
    }
}

std::size_t NInMOutQuantumGate::getNumInputs() const
{
    return mNumIn;
}

std::size_t NInMOutQuantumGate::getNumOutputs() const
{
    return mNumOut;
}

AbstractQuantumWire* NInMOutQuantumGate::getInput(std::size_t idx) const
{
    if (idx < mNumIn)
    {
        return mInputs[idx];
    }
    else
    {
        return nullptr;
    }
}

AbstractQuantumWire* NInMOutQuantumGate::getOutput(std::size_t idx) const
{
    if (idx < mNumOut)
    {
        return mOutputs[idx];
    }
    else
    {
        return nullptr;
    }
}

void NInMOutQuantumGate::setAtInput(std::size_t idx, AbstractQuantumWire* value)
{
    if (idx < mInputs.size())
    {
        mInputs[idx] = value;
    }
}

void NInMOutQuantumGate::setAtOutput(std::size_t idx, AbstractQuantumWire* value)
{
    if (idx < mOutputs.size())
    {
        mOutputs[idx] = value;
    }
}

TwoInOneOutQuantumGate::TwoInOneOutQuantumGate(AbstractQuantumWire* input0, AbstractQuantumWire* input1, AbstractQuantumWire* output)
    : NInMOutQuantumGate(2, 1, { input0, input1 }, { output })
{

}

void TwoInOneOutQuantumGate::setInput0(AbstractQuantumWire* input)
{
    setAtInput(0, input);
}

void TwoInOneOutQuantumGate::setInput1(AbstractQuantumWire* input)
{
    setAtInput(1, input);
}

void TwoInOneOutQuantumGate::setOutput(AbstractQuantumWire* output)
{
    setAtOutput(0, output);
}

OneInOneOutQuantumGate::OneInOneOutQuantumGate(AbstractQuantumWire* input, AbstractQuantumWire* output)
    : NInMOutQuantumGate(1, 1, { input }, { output })
{

}

void OneInOneOutQuantumGate::setInput(AbstractQuantumWire* input)
{
    setAtInput(0, input);
}

void OneInOneOutQuantumGate::setOutput(AbstractQuantumWire* output)
{
    setAtOutput(0, output);
}