//=============================================================================
//
// Adventure Game Studio (AGS)
//
// Copyright (C) 1999-2011 Chris Jones and 2011-2026 various contributors
// The full list of copyright holders can be found in the Copyright.txt
// file, which is part of this source code distribution.
//
// The AGS source code is provided under the Artistic License 2.0.
// A copy of this license can be found in the file License.txt and at
// https://opensource.org/license/artistic-2-0/
//
//=============================================================================
#include "ac/global_region.h"
#include "ac/common.h"
#include "ac/game_version.h"
#include "ac/gamestate.h"
#include "ac/region.h"
#include "ac/room.h"
#include "ac/roomstatus.h"
#include "dynobj/cc_region.h"
#include "debug/debug_log.h"
#include "game/roomstruct.h"
#include "gfx/bitmap.h"
#include "script/script.h"


using namespace AGS::Common;

extern RoomStruct thisroom;
extern RoomStatus*croom;
extern ScriptRegion scrRegion[MAX_ROOM_REGIONS];
extern CCRegion ccDynamicRegion;

int GetRegionIDAtRoom(int xxx, int yyy) {
    // if the co-ordinates are off the edge of the screen,
    // correct them to be just within
    // this fixes walk-off-screen problems
    xxx = room_to_mask_coord(xxx);
    yyy = room_to_mask_coord(yyy);

    if (loaded_game_file_version >= kGameVersion_262) // Version 2.6.2+
    {
        if (xxx >= thisroom.RegionMask->GetWidth())
            xxx = thisroom.RegionMask->GetWidth() - 1;
        if (yyy >= thisroom.RegionMask->GetHeight())
            yyy = thisroom.RegionMask->GetHeight() - 1;
        if (xxx < 0)
            xxx = 0;
        if (yyy < 0)
            yyy = 0;
    }

    int hsthere = thisroom.RegionMask->GetPixel (xxx, yyy);
    if (hsthere <= 0 || hsthere >= MAX_ROOM_REGIONS) return 0;
    if (croom->region_enabled[hsthere] == 0) return 0;
    return hsthere;
}

void SetAreaLightLevel(int area, int brightness) {
    if ((area < 0) || (area > MAX_ROOM_REGIONS))
        quit("!SetAreaLightLevel: invalid region");
    if (brightness < -100) brightness = -100;
    if (brightness > 100) brightness = 100;
    thisroom.Regions[area].Light = brightness;
    // disable RGB tint for this area
    thisroom.Regions[area].Tint  = 0;
    debug_script_log("Region %d light level set to %d", area, brightness);
}

void SetRegionTint (int area, int red, int green, int blue, int amount, int luminance)
{
    if ((area < 0) || (area > MAX_ROOM_REGIONS))
        quit("!SetRegionTint: invalid region");

    if ((red < 0) || (red > 255) || (green < 0) || (green > 255) ||
        (blue < 0) || (blue > 255)) {
            quit("!SetRegionTint: RGB values must be 0-255");
    }

    // originally the value was passed as 0
    // TODO: find out which versions had this; fixup only for past versions in the future!
    if (amount == 0)
        amount = 100;

    if ((amount < 1) || (amount > 100))
        quit("!SetRegionTint: amount must be 1-100");
    if ((luminance < 0) || (luminance > 100))
        quit("!SetRegionTint: luminance must be 0-100");

    debug_script_log("Region %d tint set to %d,%d,%d", area, red, green, blue);

    /*red -= 100;
    green -= 100;
    blue -= 100;*/

    thisroom.Regions[area].Tint = (red & 0xFF) |
                                   ((green & 0xFF) << 8) |
                                   ((blue & 0XFF) << 16) |
                                   ((amount & 0xFF) << 24);
    thisroom.Regions[area].Light = (luminance * 25) / 10;
}

void DisableRegion(int hsnum) {
    if ((hsnum < 0) || (hsnum >= MAX_ROOM_REGIONS))
        quit("!DisableRegion: invalid region specified");

    croom->region_enabled[hsnum] = 0;
    debug_script_log("Region %d disabled", hsnum);
}

void EnableRegion(int hsnum) {
    if ((hsnum < 0) || (hsnum >= MAX_ROOM_REGIONS))
        quit("!EnableRegion: invalid region specified");

    croom->region_enabled[hsnum] = 1;
    debug_script_log("Region %d enabled", hsnum);
}

void DisableGroundLevelAreas(int alsoEffects) {
    if ((alsoEffects < 0) || (alsoEffects > 1))
        quit("!DisableGroundLevelAreas: invalid parameter: must be 0 or 1");

    play.ground_level_areas_disabled = GLED_INTERACTION;

    if (alsoEffects)
        play.ground_level_areas_disabled |= GLED_EFFECTS;

    debug_script_log("Ground-level areas disabled");
}

void EnableGroundLevelAreas() {
    play.ground_level_areas_disabled = 0;

    debug_script_log("Ground-level areas re-enabled");
}

void RunRegionInteraction (int regnum, int mood) {
    if ((regnum < 0) || (regnum >= MAX_ROOM_REGIONS))
        quit("!RunRegionInteraction: invalid region speicfied");
    if ((mood < 0) || (mood > 2))
        quit("!RunRegionInteraction: invalid event specified");

    // NOTE: for Regions the mode has specific meanings (NOT verbs):
    // 0 - stands on region, 1 - walks onto region, 2 - walks off region
    const auto obj_evt = ObjectEvent(kScTypeRoom, "region%d", regnum,
        RuntimeScriptValue().SetScriptObject(&scrRegion[regnum], &ccDynamicRegion), mood);
    if (loaded_game_file_version > kGameVersion_272)
    {
        run_interaction_script(obj_evt, thisroom.Regions[regnum].EventHandlers.get(), mood);
    }
    else
    {
        run_interaction_event(obj_evt, &croom->intrRegion[regnum], mood);
    }
}
