/*****************************************************************************
 * 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 "../Paint.h"

#include "../../Game.h"
#include "../../GameState.h"
#include "../../config/Config.h"
#include "../../drawing/Drawing.h"
#include "../../interface/Viewport.h"
#include "../../localisation/Formatter.h"
#include "../../localisation/Formatting.h"
#include "../../localisation/StringIds.h"
#include "../../object/BannerObject.h"
#include "../../object/ObjectEntryManager.h"
#include "../../profiling/Profiling.h"
#include "../../ride/TrackDesign.h"
#include "../../world/Banner.h"
#include "../../world/Scenery.h"
#include "../../world/TileInspector.h"
#include "../../world/tile_element/BannerElement.h"
#include "Paint.Banner.h"
#include "Paint.TileElement.h"

using namespace OpenRCT2;
using namespace OpenRCT2::Drawing;

// kBannerBoundBoxes[rotation][0] is for the pole in the back
// kBannerBoundBoxes[rotation][1] is for the pole and the banner in the front
const CoordsXY kBannerBoundBoxes[][2] = {
    { { 1, 2 }, { 1, 29 } },
    { { 2, 32 }, { 29, 32 } },
    { { 32, 2 }, { 32, 29 } },
    { { 2, 1 }, { 29, 1 } },
};

static void PaintBannerScrollingText(
    PaintSession& session, const BannerSceneryEntry& bannerEntry, Banner& banner, const BannerElement& bannerElement,
    Direction direction, int32_t height, const CoordsXYZ& bbOffset)
{
    PROFILED_FUNCTION();

    // If text on hidden direction or ghost
    direction = DirectionReverse(direction) - 1;
    if (direction >= 2 || (bannerElement.IsGhost()))
        return;

    auto scrollingMode = bannerEntry.scrolling_mode + (direction & 3);
    if (scrollingMode >= ScrollingText::kMaxModes)
    {
        return;
    }

    auto bannerText = banner.getTextWithColour();
    auto imageId = ScrollingText::setup(session, bannerText, scrollingMode, PaletteIndex::transparent);
    PaintAddImageAsChild(session, imageId, { 0, 0, height + 22 }, { bbOffset, { 1, 1, 21 } });
}

void PaintBanner(PaintSession& session, uint8_t direction, int32_t height, const BannerElement& bannerElement)
{
    PROFILED_FUNCTION();

    if (session.rt.zoom_level > ZoomLevel{ 1 } || gTrackDesignSaveMode
        || (session.ViewFlags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES))
        return;

    auto banner = bannerElement.GetBanner();
    if (banner == nullptr)
    {
        return;
    }

    auto* bannerEntry = OpenRCT2::ObjectEntryManager::GetObjectEntry<BannerSceneryEntry>(banner->type);
    if (bannerEntry == nullptr)
    {
        return;
    }

    session.InteractionType = ViewportInteractionItem::banner;

    height -= 16;

    direction += bannerElement.GetPosition();
    direction &= 3;

    ImageId imageTemplate;
    if (bannerElement.IsGhost())
    {
        session.InteractionType = ViewportInteractionItem::none;
        imageTemplate = ImageId().WithRemap(FilterPaletteID::paletteGhost);
    }
    else if (session.SelectedElement == reinterpret_cast<const TileElement*>(&bannerElement))
    {
        imageTemplate = ImageId().WithRemap(FilterPaletteID::paletteGhost);
    }
    else
    {
        imageTemplate = ImageId().WithPrimary(banner->colour);
    }

    auto imageIndex = (direction << 1) + bannerEntry->image;
    auto imageId = imageTemplate.WithIndex(imageIndex);
    auto bbOffset = CoordsXYZ(kBannerBoundBoxes[direction][0], height + 2);
    PaintAddImageAsParent(session, imageId, { 0, 0, height }, { bbOffset, { 1, 1, 21 } });

    bbOffset = CoordsXYZ(kBannerBoundBoxes[direction][1], height + 2);
    PaintAddImageAsParent(session, imageId.WithIndexOffset(1), { 0, 0, height }, { bbOffset, { 1, 1, 21 } });

    PaintBannerScrollingText(session, *bannerEntry, *banner, bannerElement, direction, height, bbOffset);
}
