#include "ChunkMap.h"

#include "Constants.h"

ChunkMap::ChunkMap(Framework::StreamReader* zReader)
    : ReferenceCounter(),
      maxHeight(0)
{
    pixels = new MapPixel[CHUNK_SIZE * CHUNK_SIZE];
    memset(pixels, 0, sizeof(MapPixel) * CHUNK_SIZE * CHUNK_SIZE);
    heightMap = new unsigned char[CHUNK_SIZE * CHUNK_SIZE];
    memset(heightMap, 0, CHUNK_SIZE * CHUNK_SIZE);
    zReader->read((char*)&chunkCenter.x, 4);
    zReader->read((char*)&chunkCenter.y, 4);
    for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++)
    {
        zReader->read((char*)&pixels[i].len, 1);
        if (pixels[i].len > 0)
        {
            pixels[i].blocks = new MapBlock[pixels[i].len];
            zReader->read(
                (char*)pixels[i].blocks, (int)sizeof(MapBlock) * pixels[i].len);
        }
    }
    rendered.newImage(16, 16, 0xA0000000);
    setMaxHeight(255);
}

ChunkMap::ChunkMap(Framework::Point center)
    : ReferenceCounter(),
      chunkCenter(center),
      maxHeight(0)
{
    pixels = new MapPixel[CHUNK_SIZE * CHUNK_SIZE];
    memset(pixels, 0, sizeof(MapPixel) * CHUNK_SIZE * CHUNK_SIZE);
    heightMap = new unsigned char[CHUNK_SIZE * CHUNK_SIZE];
    memset(heightMap, 0, CHUNK_SIZE * CHUNK_SIZE);
    rendered.newImage(16, 16, 0xA0000000);
    setMaxHeight(255);
}

ChunkMap::~ChunkMap()
{
    for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++)
    {
        delete[] pixels[i].blocks;
    }
    delete[] pixels;
    delete[] heightMap;
}

void ChunkMap::setMaxHeight(unsigned char maxHeight)
{
    if (maxHeight != this->maxHeight)
    {
        rendered.fillRegion(0, 0, CHUNK_SIZE, CHUNK_SIZE, 0xA0000000);
        memset(heightMap, 0, CHUNK_SIZE * CHUNK_SIZE);
        this->maxHeight = maxHeight;
        for (int x = 0; x < CHUNK_SIZE; x++)
        {
            for (int y = 0; y < CHUNK_SIZE; y++)
            {
                int i = x * CHUNK_SIZE + y;
                bool first = 1;
                for (int j = 0; j < pixels[i].len
                                && pixels[i].blocks[j].height <= maxHeight;
                     j++)
                {
                    if (first)
                    {
                        rendered.setPixelDP(x, y, 0xFF000000);
                        first = 0;
                    }
                    rendered.alphaPixel2D(x, y, pixels[i].blocks[j].color);
                    heightMap[y * CHUNK_SIZE + x] = pixels[i].blocks[j].height;
                }
            }
        }
    }
}

const Framework::Image& ChunkMap::getRenderedImage() const
{
    return rendered;
}

unsigned char* ChunkMap::getHeightMap() const
{
    return heightMap;
}

Framework::Point ChunkMap::getChunkCenter() const
{
    return chunkCenter;
}