//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// storeimage_paletted.cpp: Encodes GL_PALETTE_* textures.

#include <unordered_map>
#include "common/unsafe_buffers.h"

#include "image_util/storeimage.h"

#include <type_traits>
#include "common/mathutil.h"

#include "image_util/imageformats.h"

namespace angle
{

namespace
{

template <typename T>
inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
{
    return reinterpret_cast<T *>(ANGLE_UNSAFE_TODO(data + (y * rowPitch) + (z * depthPitch)));
}

template <typename T>
inline const T *OffsetDataPointer(const uint8_t *data,
                                  size_t y,
                                  size_t z,
                                  size_t rowPitch,
                                  size_t depthPitch)
{
    return reinterpret_cast<const T *>(ANGLE_UNSAFE_TODO(data + (y * rowPitch) + (z * depthPitch)));
}

void EncodeColor(R8G8B8A8 rgba,
                 uint32_t redBlueBits,
                 uint32_t greenBits,
                 uint32_t alphaBits,
                 void *dst)
{
    gl::ColorF color;
    R8G8B8A8::readColor(&color, &rgba);

    switch (redBlueBits)
    {
        case 8:
            ASSERT(greenBits == 8);
            switch (alphaBits)
            {
                case 0:
                    return R8G8B8::writeColor(reinterpret_cast<R8G8B8 *>(dst), &color);
                case 8:
                    return R8G8B8A8::writeColor(reinterpret_cast<R8G8B8A8 *>(dst), &color);
                default:
                    UNREACHABLE();
                    break;
            }
            break;

        case 5:
            switch (greenBits)
            {
                case 6:
                    ASSERT(alphaBits == 0);
                    return R5G6B5::writeColor(reinterpret_cast<R5G6B5 *>(dst), &color);
                case 5:
                    ASSERT(alphaBits == 1);
                    return R5G5B5A1::writeColor(reinterpret_cast<R5G5B5A1 *>(dst), &color);
                default:
                    UNREACHABLE();
                    break;
            }
            break;

        case 4:
            ASSERT(greenBits == 4 && alphaBits == 4);
            return R4G4B4A4::writeColor(reinterpret_cast<R4G4B4A4 *>(dst), &color);

        default:
            UNREACHABLE();
            break;
    }
}

uint32_t R8G8B8A8Key(R8G8B8A8 rgba)
{
    uint32_t key;
    static_assert(sizeof(key) == sizeof(rgba));
    ANGLE_UNSAFE_TODO(memcpy(&key, &rgba, sizeof(key)));
    return key;
}

}  // namespace

void StoreRGBA8ToPalettedImpl(size_t width,
                              size_t height,
                              size_t depth,
                              uint32_t indexBits,
                              uint32_t redBlueBits,
                              uint32_t greenBits,
                              uint32_t alphaBits,
                              const uint8_t *input,
                              size_t inputRowPitch,
                              size_t inputDepthPitch,
                              uint8_t *output,
                              size_t outputRowPitch,
                              size_t outputDepthPitch)
{
    std::unordered_map<uint32_t, size_t> invPalette;

    ASSERT((redBlueBits + greenBits + redBlueBits + alphaBits) % 8 == 0);

    size_t colorBytes   = (redBlueBits + greenBits + redBlueBits + alphaBits) / 8;
    size_t paletteSize  = 1 << indexBits;
    size_t paletteBytes = paletteSize * colorBytes;

    uint8_t *palette = output;

    // We might not fill-out the entire palette.
    ANGLE_UNSAFE_TODO(memset(palette, 0xab, paletteBytes));

    uint8_t *texels = ANGLE_UNSAFE_TODO(
        output + paletteBytes);  // + TODO(http://anglebug.com/42266155): mip levels

    for (size_t z = 0; z < depth; z++)
    {
        for (size_t y = 0; y < height; y++)
        {
            const R8G8B8A8 *srcRow =
                OffsetDataPointer<R8G8B8A8>(input, y, z, inputRowPitch, inputDepthPitch);
            uint8_t *dstRow =
                OffsetDataPointer<uint8_t>(texels, y, z, outputRowPitch, outputDepthPitch);

            for (size_t x = 0; x < width; x++)
            {
                auto inversePaletteEntry = invPalette.insert(std::pair<uint32_t, size_t>(
                    R8G8B8A8Key(ANGLE_UNSAFE_TODO(srcRow[x])), invPalette.size()));
                size_t paletteIndex = inversePaletteEntry.first->second;
                ASSERT(paletteIndex < paletteSize);
                if (inversePaletteEntry.second)
                {
                    ANGLE_UNSAFE_TODO({
                        EncodeColor(srcRow[x], redBlueBits, greenBits, alphaBits,
                                    palette + paletteIndex * colorBytes);
                    })
                }

                switch (indexBits)
                {
                    case 4:
                        // On even xses, initialize the location and store the high
                        // bits, on odd (which always follows even) store the low
                        // bits.
                        if (x % 2 == 0)
                            ANGLE_UNSAFE_TODO(dstRow[x / 2]) = static_cast<uint8_t>(paletteIndex)
                                                               << 4;
                        else
                            ANGLE_UNSAFE_TODO(dstRow[x / 2]) |= static_cast<uint8_t>(paletteIndex);
                        break;

                    case 8:
                        ANGLE_UNSAFE_TODO(dstRow[x]) = static_cast<uint8_t>(paletteIndex);
                        break;

                    default:
                        UNREACHABLE();
                }
            }
        }
    }
}

}  // namespace angle
