#pragma once

#include <register/hei_register.hpp>

/**
 * @file hei_operator_register.hpp
 *
 * A library of useful classes used to perform logical or bitwise math on or
 * between other registers. The classes implemented here include NotRegister,
 * LeftShiftRegister, RightShiftRegister, AndRegister, OrRegister, and
 * ConstantRegister.
 *
 * Accompanied with other Register classes and the getBitString() function, it
 * is possible to perform operations like:
 *
 *      AndRegister reg{<register1>,<register2>};
 *      result = reg.getBitString(<someChip>);
 *
 * This example will return a BitString containing the result of the bitwise
 * AND operation applied to register1 and register2.
 */
namespace libhei
{

/**
 * @brief An abstract class for all operator registers.
 *
 * Contains member functions and variables that are required for all child
 * classes.
 */
class OperatorRegister : public Register
{
  public:
    /** @brief Pure virtual destructor. */
    virtual ~OperatorRegister() = 0;

  protected:
    /**
     * @brief Constructor from components.
     * @param i_size Size (in bytes) of this register.
     */
    explicit OperatorRegister(size_t i_size) : Register(), iv_result(i_size * 8)
    {}

  protected: // Instance variables
    /** When getBitString() is called on an operator, the resulting value of the
     *  operation will be stored in this instance variable. */
    BitStringBuffer iv_result;

  public:
    /** @brief Overloaded from parent class. */
    size_t getSize() const override
    {
        return (BitString::getMinBytes(iv_result.getBitLen()));
    }
};

// Pure virtual destructor must be defined.
inline OperatorRegister::~OperatorRegister() {}

/**
 * @brief Using getBitString(), performs a bitwise NOT operation on a register.
 *
 * Example:
 *      NotRegister reg{someRegister};
 *      result = reg.getBitString(someChip);
 */
class NotRegister : public OperatorRegister
{
  public:
    /**
     * @brief Constructor from components.
     * @param i_arg Target register for operation.
     */
    explicit NotRegister(Register::ConstPtr i_arg) :
        OperatorRegister(i_arg->getSize()), iv_child(i_arg)
    {}

    /** @brief Destructor. */
    ~NotRegister() = default;

    /** @brief Copy constructor. */
    NotRegister(const NotRegister&) = delete;

    /** @brief Assignment operator. */
    NotRegister& operator=(const NotRegister& r) = delete;

    /** @brief Overloaded from parent class. */
    const BitString* getBitString(const Chip& i_chip) const override
    {
        const auto* bs = iv_child->getBitString(i_chip);

        (const_cast<NotRegister*>(this))->iv_result = ~(*bs);

        return &iv_result;
    }

    /** @brief Comparison operator. */
    bool operator==(const NotRegister& r) const
    {
        return iv_child == r.iv_child;
    }

    /** @brief Less-than operator. */
    bool operator<(const NotRegister& r) const
    {
        return iv_child < r.iv_child;
    }

  private:
    const Register::ConstPtr iv_child;
};

/**
 * @brief Using getBitString(), performs a left shift operation on a register.
 *
 * Example:
 *      LeftShiftRegister reg{someRegister1, shiftValue};
 *      result = reg.getBitString(someChip);
 */
class LeftShiftRegister : public OperatorRegister
{
  public:
    /**
     * @brief Constructor from components.
     * @param i_arg    Target register for operation.
     * @param i_amount The shift value.
     */
    LeftShiftRegister(Register::ConstPtr i_arg, size_t i_amount) :
        OperatorRegister(i_arg->getSize()), iv_child(i_arg), iv_amount(i_amount)
    {}

    /** @brief Destructor. */
    ~LeftShiftRegister() = default;

    /** @brief Copy constructor. */
    LeftShiftRegister(const LeftShiftRegister&) = delete;

    /** @brief Assignment operator. */
    LeftShiftRegister& operator=(const LeftShiftRegister& r) = delete;

    /** @brief Overloaded from parent class. */
    const BitString* getBitString(const Chip& i_chip) const override
    {
        const auto* bs = iv_child->getBitString(i_chip);

        (const_cast<LeftShiftRegister*>(this))->iv_result = (*bs) << iv_amount;

        return &iv_result;
    }

    /** @brief Comparison operator. */
    bool operator==(const LeftShiftRegister& r) const
    {
        return (iv_child == r.iv_child) && (iv_amount == r.iv_amount);
    }

    /** @brief Less-than operator. */
    bool operator<(const LeftShiftRegister& r) const
    {
        if (iv_child == r.iv_child)
            return iv_amount < r.iv_amount;
        return iv_child < r.iv_child;
    }

  private:
    const Register::ConstPtr iv_child;
    const size_t iv_amount;
};

/**
 * @brief Using getBitString(), performs a right shift operation on a register.
 *
 * Example:
 *      RightShiftRegister reg{someRegister1, shiftValue};
 *      result = reg.getBitString(someChip);
 */
class RightShiftRegister : public OperatorRegister
{
  public:
    /**
     * @brief Constructor from components.
     * @param i_arg    Target register for operation.
     * @param i_amount The shift value.
     */
    RightShiftRegister(Register::ConstPtr i_arg, size_t i_amount) :
        OperatorRegister(i_arg->getSize()), iv_child(i_arg), iv_amount(i_amount)
    {}

    /** @brief Destructor. */
    ~RightShiftRegister() = default;

    /** @brief Copy constructor. */
    RightShiftRegister(const RightShiftRegister&) = delete;

    /** @brief Assignment operator. */
    RightShiftRegister& operator=(const RightShiftRegister& r) = delete;

    /** @brief Overloaded from parent class. */
    const BitString* getBitString(const Chip& i_chip) const override
    {
        const auto* bs = iv_child->getBitString(i_chip);

        (const_cast<RightShiftRegister*>(this))->iv_result = (*bs) >> iv_amount;

        return &iv_result;
    }

    /** @brief Comparison operator. */
    bool operator==(const RightShiftRegister& r) const
    {
        return (iv_child == r.iv_child) && (iv_amount == r.iv_amount);
    }

    /** @brief Less-than operator. */
    bool operator<(const RightShiftRegister& r) const
    {
        if (iv_child == r.iv_child)
            return iv_amount < r.iv_amount;
        return iv_child < r.iv_child;
    }

  private:
    const Register::ConstPtr iv_child;
    const size_t iv_amount;
};

/**
 * @brief Using getBitString(), performs a bitwise AND operation on a pair
 *        of registers.
 *
 * Example:
 *      AndRegister reg{someRegister1, someRegister2};
 *      result = reg.getBitString(someChip);
 */
class AndRegister : public OperatorRegister
{
  public:
    /**
     * @brief Constructor from components.
     * @param i_left  Target register for operation.
     * @param i_right Target register for operation.
     */
    AndRegister(Register::ConstPtr i_left, Register::ConstPtr i_right) :
        OperatorRegister(i_left->getSize()), iv_left(i_left), iv_right(i_right)
    {
        // The two registers must be the same sizes or it makes for some weird
        // results.
        HEI_ASSERT(iv_left->getSize() == iv_right->getSize());
    }

    /** @brief Destructor. */
    ~AndRegister() = default;

    /** @brief Copy constructor. */
    AndRegister(const AndRegister&) = delete;

    /** @brief Assignment operator. */
    AndRegister& operator=(const AndRegister& r) = delete;

    /** @brief Overloaded from parent class. */
    const BitString* getBitString(const Chip& i_chip) const override
    {
        const auto* l_bs = iv_left->getBitString(i_chip);
        const auto* r_bs = iv_right->getBitString(i_chip);

        (const_cast<AndRegister*>(this))->iv_result = (*l_bs) & (*r_bs);

        return &iv_result;
    }

    /** @brief Comparison operator. */
    bool operator==(const AndRegister& r) const
    {
        return (iv_left == r.iv_left) && (iv_right == r.iv_right);
    }

    /** @brief Less-than operator. */
    bool operator<(const AndRegister& r) const
    {
        if (iv_left == r.iv_left)
            return iv_right < r.iv_right;
        return iv_left < r.iv_left;
    }

  private:
    const Register::ConstPtr iv_left;
    const Register::ConstPtr iv_right;
};

/**
 * @brief Using getBitString(), performs a bitwise OR operation on a pair
 *        of registers.
 *
 * Example:
 *      OrRegister reg{someRegister1, someRegister2};
 *      result = reg.getBitString(someChip);
 */
class OrRegister : public OperatorRegister
{
  public:
    /**
     * @brief Constructor from components.
     * @param i_left  Target register for operation.
     * @param i_right Target register for operation.
     */
    OrRegister(Register::ConstPtr i_left, Register::ConstPtr i_right) :
        OperatorRegister(i_left->getSize()), iv_left(i_left), iv_right(i_right)
    {
        // The two registers must be the same sizes or it makes for some weird
        // results.
        HEI_ASSERT(iv_left->getSize() == iv_right->getSize());
    }

    /** @brief Destructor. */
    ~OrRegister() = default;

    /** @brief Copy constructor. */
    OrRegister(const OrRegister&) = delete;

    /** @brief Assignment operator. */
    OrRegister& operator=(const OrRegister& r) = delete;

    /** @brief Overloaded from parent class. */
    const BitString* getBitString(const Chip& i_chip) const override
    {
        const auto* l_bs = iv_left->getBitString(i_chip);
        const auto* r_bs = iv_right->getBitString(i_chip);

        (const_cast<OrRegister*>(this))->iv_result = (*l_bs) | (*r_bs);

        return &iv_result;
    }

    /** @brief Comparison operator. */
    bool operator==(const OrRegister& r) const
    {
        return (iv_left == r.iv_left) && (iv_right == r.iv_right);
    }

    /** @brief Less-than operator. */
    bool operator<(const OrRegister& r) const
    {
        if (iv_left == r.iv_left)
            return iv_right < r.iv_right;
        return iv_left < r.iv_left;
    }

  private:
    const Register::ConstPtr iv_left;
    const Register::ConstPtr iv_right;
};

/**
 * @brief Contains a constant value that can be used within any of the other
 *        register operators. The value can be retrieved using the
 *        getBitString() function.
 */
class ConstantRegister : public OperatorRegister
{
  public:
    /**
     * @brief Constructor from components.
     * @param i_val An unsigned integer value. iv_result will be initialized to
     *              the size of type T and this value will be copied into that
     *              buffer.
     */
    template <class T>
    explicit ConstantRegister(T i_val) : OperatorRegister(sizeof(i_val))
    {
        iv_result.setFieldRight(0, iv_result.getBitLen(), i_val);
    }

    /** @brief Destructor. */
    ~ConstantRegister() = default;

    /** @brief Copy constructor. */
    ConstantRegister(const ConstantRegister&) = delete;

    /** @brief Assignment operator. */
    ConstantRegister& operator=(const ConstantRegister& r) = delete;

    /** @brief Overloaded from parent class. */
    const BitString* getBitString(const Chip& i_chip) const override
    {
        return &iv_result;
    }

    /** @brief Comparison operator. */
    bool operator==(const ConstantRegister& r) const
    {
        return iv_result == r.iv_result;
    }

    /** @brief Less-than operator. */
    bool operator<(const ConstantRegister& r) const
    {
        return iv_result < r.iv_result;
    }
};

} // end namespace libhei
