/*
    Open1560 - An Open Source Re-Implementation of Midtown Madness 1 Beta
    Copyright (C) 2020 Brick

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

class agiTexLut;
class agiTexParameters;
class agiColorModel;

struct agiColorKey // DDCOLORKEY
{
    u32 Low {};
    u32 High {};
};

#define AGIPF_ALPHAPIXELS 0x00000001l
#define AGIPF_ALPHA 0x00000002l
#define AGIPF_FOURCC 0x00000004l
#define AGIPF_PALETTEINDEXED4 0x00000008l
#define AGIPF_PALETTEINDEXEDTO8 0x00000010l
#define AGIPF_PALETTEINDEXED8 0x00000020l
#define AGIPF_RGB 0x00000040l

struct agiPixelFormat // DDPIXELFORMAT
{
    u32 Size {};
    u32 Flags {};
    u32 FourCC {};
    u32 RGBBitCount {};
    u32 RBitMask {};
    u32 GBitMask {};
    u32 BBitMask {};
    u32 RGBAlphaBitMask {};
};

extern const agiPixelFormat PixelFormat_A8R8G8B8;
extern const agiPixelFormat PixelFormat_A8B8G8R8;
extern const agiPixelFormat PixelFormat_X8R8G8B8;
extern const agiPixelFormat PixelFormat_X8B8G8R8;

extern const agiPixelFormat PixelFormat_A4R4G4B4;
extern const agiPixelFormat PixelFormat_A1R5G5B5;
extern const agiPixelFormat PixelFormat_X1R5G5B5;
extern const agiPixelFormat PixelFormat_R5G6B5;

extern const agiPixelFormat PixelFormat_P8;

extern const agiPixelFormat PixelFormat_B8G8R8;

struct agiDDSCAPS2 // DDSCAPS2
{
    u32 Caps {};
    u32 Caps2 {};
    u32 Caps3 {};
    u32 Caps4 {};
};

#define AGISD_HEIGHT 0x00000002l
#define AGISD_WIDTH 0x00000004l
#define AGISD_PITCH 0x00000008l
#define AGISD_PIXELFORMAT 0x00001000l
#define AGISD_CKDESTOVERLAY 0x00002000l
#define AGISD_CKDESTBLT 0x00004000l
#define AGISD_CKSRCOVERLAY 0x00008000l
#define AGISD_CKSRCBLT 0x00010000l
#define AGISD_MIPMAPCOUNT 0x00020000l
#define AGISD_LINEARSIZE 0x00080000l

// TODO: Allow safe conversion to/from DDSURFACEDESC2 (instead of bitcasting)

class agiSurfaceDesc // DDSURFACEDESC2
{
public:
    // ?CopyFrom@agiSurfaceDesc@@QAEXPAV1@H@Z
    void CopyFrom(agiSurfaceDesc* src, i32 src_lod);

    void CopyFrom(agiSurfaceDesc* src, i32 src_lod, agiTexParameters* params);

    // ?Reload@agiSurfaceDesc@@QAEXPAD0HHPAVStream@@HH@Z
    ARTS_IMPORT void Reload(aconst char* arg1, aconst char* arg2, i32 arg3, i32 arg4, Stream* arg5, i32 arg6, i32 arg7);

    // ?Unload@agiSurfaceDesc@@QAEXXZ
    void Unload();

    // ?Init@agiSurfaceDesc@@SAPAV1@HHAAV1@@Z
    [[nodiscard]] static Owner<agiSurfaceDesc> Init(i32 width, i32 height, const agiSurfaceDesc& desc);

    void Load();

    // ?Load@agiSurfaceDesc@@SAPAV1@PAD0HHHH@Z
    [[nodiscard]] ARTS_IMPORT static Owner<agiSurfaceDesc> Load(
        aconst char* name, aconst char* path, i32 index, i32 pack, i32 width, i32 height);

    void Clear();
    void Clear(i32 x, i32 y, i32 width, i32 height);

    void Fill(i32 x, i32 y, i32 width, i32 height, u32 color);

    void FixPitch();

    static agiSurfaceDesc FromFormat(const agiPixelFormat& format);

    Rc<agiColorModel> GetColorModel();

    u32 GetPixelSize() const
    {
        return (PixelFormat.RGBBitCount + 7) / 8;
    }

    u32 Size {};
    u32 Flags {};
    u32 Height {};
    u32 Width {};
    i32 Pitch {};
    u32 BackBufferCount {};
    u32 MipMapCount {};
    u32 AlphaBitDepth {};

    union
    {
        // NOTE: 64-bit incompatible
        agiTexLut* lpLut {};
        char szLut[4];
    };

    void* Surface {};
    agiColorKey DestOverlay {};
    agiColorKey DestBlt {};
    agiColorKey SrcOverlay {};
    agiColorKey SrcBlt {};
    agiPixelFormat PixelFormat {};
    agiDDSCAPS2 SCaps {};
    u32 TextureStage {};
};

check_size(agiSurfaceDesc, 0x7C);

// ?AnnotateTextures@@3HA
ARTS_IMPORT extern b32 AnnotateTextures;
