/*****************************************************************************
 * Copyright (c) 2014-2026 OpenRCT2 developers
 *
 * For a complete list of all authors, please refer to contributors.md
 * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
 *
 * OpenRCT2 is licensed under the GNU General Public License version 3.
 *****************************************************************************/

#include "QuarterTile.h"

#include "../Diagnostic.h"
#include "../world/Map.h"

// Rotate both of the values amount
const QuarterTile QuarterTile::Rotate(uint8_t amount) const
{
    switch (amount)
    {
        case 0:
            return QuarterTile{ *this };
        case 1:
        {
            auto rotVal1 = _val << 1;
            auto rotVal2 = rotVal1 >> 4;
            // Clear the bit from the tileQuarter
            rotVal1 &= 0b11101110;
            // Clear the bit from the zQuarter
            rotVal2 &= 0b00010001;
            return QuarterTile{ static_cast<uint8_t>(rotVal1 | rotVal2) };
        }
        case 2:
        {
            auto rotVal1 = _val << 2;
            auto rotVal2 = rotVal1 >> 4;
            // Clear the bit from the tileQuarter
            rotVal1 &= 0b11001100;
            // Clear the bit from the zQuarter
            rotVal2 &= 0b00110011;
            return QuarterTile{ static_cast<uint8_t>(rotVal1 | rotVal2) };
        }
        case 3:
        {
            auto rotVal1 = _val << 3;
            auto rotVal2 = rotVal1 >> 4;
            // Clear the bit from the tileQuarter
            rotVal1 &= 0b10001000;
            // Clear the bit from the zQuarter
            rotVal2 &= 0b01110111;
            return QuarterTile{ static_cast<uint8_t>(rotVal1 | rotVal2) };
        }
        default:
            LOG_ERROR("Tried to rotate QuarterTile invalid amount.");
            return QuarterTile{ 0 };
    }
}

uint8_t QuarterTile::GetBaseQuarterOccupied() const
{
    return _val & 0xF;
}

uint8_t QuarterTile::GetZQuarterOccupied() const
{
    return (_val >> 4) & 0xF;
}

TileCornersZ QuarterTile::GetQuarterHeights(const int32_t height) const
{
    const uint8_t raisedQuarters = GetZQuarterOccupied();
    const int32_t northZ = height + (raisedQuarters & 0b0001 ? kLandHeightStep : 0);
    const int32_t eastZ = height + (raisedQuarters & 0b0010 ? kLandHeightStep : 0);
    const int32_t southZ = height + (raisedQuarters & 0b0100 ? kLandHeightStep : 0);
    const int32_t westZ = height + (raisedQuarters & 0b1000 ? kLandHeightStep : 0);
    return { northZ, eastZ, southZ, westZ };
}
