#include "level.h"
#include "resources.h"
#include "factory_objects.h"
#include "camera.h"
#include "utils.h"
#include "player.h"

typedef enum fog_type_e
{
    FOG_FILL  = 0,
    FOG_0     = 1,
    FOG_1     = 2,
    FOG_2     = 3,
    FOG_3     = 4,
    FOG_4     = 5,
    FOG_12    = 6,
    FOG_13    = 7,
    FOG_14    = 8,
    FOG_23    = 9,
    FOG_24    = 10,
    FOG_34    = 11,
    FOG_123   = 12,
    FOG_124   = 13,
    FOG_234   = 14,
    FOG_134   = 15
} fog_type_t;

typedef struct level_cells_s
{
    unsigned char collision;
    unsigned char object;
    unsigned char tile;
    unsigned char back;
    bool       fog;
    fog_type_t fog_type;
} level_cells_t;

static int level_cells_width  = 0;
static int level_cells_height = 0;
static int level_width        = 0;
static int level_height       = 0;

static level_cells_t **level_cells = NULL;

static bool _Level_Load(const char *filename)
{
    unsigned int i    = 0;
    unsigned int x    = 0;
    unsigned int y    = 0;
    FILE        *file = NULL;

    file = fopen(filename, "rb");

    if (file == NULL)
    {
        fclose(file);

        return false;
    }

    fread(&level_cells_width,  sizeof(level_cells_width),  1, file);
    fread(&level_cells_height, sizeof(level_cells_height), 1, file);

    level_width  = level_cells_width  * CELL_WIDTH;
    level_height = level_cells_height * CELL_HEIGHT;

    level_cells = (level_cells_t**) malloc(level_cells_width * sizeof(level_cells_t*));

    for (i = 0; i < level_cells_width; ++i)
    {
        level_cells[i] = (level_cells_t*) malloc(level_cells_height * sizeof(level_cells_t));
    }

    // read level :)
    // 1. collisions
    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            fread(&level_cells[x][y].collision, sizeof(level_cells[x][y].collision), 1, file);
        }
    }
    // 2. objects
    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            fread(&level_cells[x][y].object, sizeof(level_cells[x][y].object), 1, file);
        }
    }
    // 3. tiles
    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            fread(&level_cells[x][y].tile, sizeof(level_cells[x][y].tile), 1, file);
        }
    }
    // 4. back
    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            fread(&level_cells[x][y].back, sizeof(level_cells[x][y].back), 1, file);
        }
    }

    fclose(file);

    return true;
}

static void _Level_CreateObjects(void)
{
    object_t *object = NULL;

    unsigned int i  = 0;
    unsigned int x  = 0;
    unsigned int y  = 0;
    int          ox = 0;
    int          oy = 0;

    object = FactoryObjects_Create();
    Actor_Back_Create(object, level_width, level_height);

    object = FactoryObjects_Create();
    Actor_Tiles_Create(object, level_width, level_height);

    int count_clouds = (level_cells_width * level_cells_height) / 30;

    if (count_clouds > 0)
    {
        for (i = 0; i < count_clouds; ++i)
        {
            ox = Utils_GetRandomRange(0, level_width);
            oy = Utils_GetRandomRange(0, level_height);

            object = FactoryObjects_Create();
            Actor_Cloud_Create(object , ox, oy);
        }
    }

    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            ox = (x * CELL_WIDTH);
            oy = (y * CELL_HEIGHT);

            // robo
            if (level_cells[x][y].object == ID_CELL_ROBO_START)
            {
                object = FactoryObjects_Create();
                Actor_Spawn_Create(object, ox - 12, oy - 12, false);

                vector_t position = Utils_GetVector(ox, oy);
                Level_OpenFogInPosition(position);
                position = Utils_GetVector(ox + 15, oy + 12);
                Camera_SetFollowPosition(position);
            }

            // teleport (robo_finish)
            if (level_cells[x][y].object == ID_CELL_ROBO_FINISH)
            {
                object = FactoryObjects_Create();
                Actor_Teleport_Create(object, ox, oy);
            }

            // coin
            if (level_cells[x][y].object == ID_CELL_COIN)
            {
                object = FactoryObjects_Create();
                Actor_Coin_Create(object, ox + 24, oy + 24);
            }

            // diamond
            if (level_cells[x][y].object == ID_CELL_DIAMOND)
            {
                object = FactoryObjects_Create();
                Actor_Diamond_Create(object, ox + 24, oy + 24);
            }

            // checkpoint
            if (level_cells[x][y].object == ID_CELL_CHECKPOINT)
            {
                object = FactoryObjects_Create();
                Actor_Checkpoint_Create(object, ox + 24, oy + 12);
            }


            // wallfirer
            if (level_cells[x][y].object == ID_CELL_WALLFIRER_U)
            {
                object = FactoryObjects_Create();
                Actor_Wallfirer_Create(object, 0, ox + 24, oy + 24);
            }

            // wallfirer
            if (level_cells[x][y].object == ID_CELL_WALLFIRER_R)
            {
                object = FactoryObjects_Create();
                Actor_Wallfirer_Create(object, 1, ox + 24, oy + 24);
            }

            // wallfirer
            if (level_cells[x][y].object == ID_CELL_WALLFIRER_D)
            {
                object = FactoryObjects_Create();
                Actor_Wallfirer_Create(object, 2, ox + 24, oy + 24);
            }

            // wallfirer
            if (level_cells[x][y].object == ID_CELL_WALLFIRER_L)
            {
                object = FactoryObjects_Create();
                Actor_Wallfirer_Create(object, 3, ox + 24, oy + 24);
            }

            // spikes
            if (level_cells[x][y].object == ID_CELL_SPIKES)
            {
                object = FactoryObjects_Create();
                Actor_Spikes_Create(object, ox + 24, oy + 24);
            }

            // hammer
            if (level_cells[x][y].object == ID_CELL_HAMMER)
            {
                object = FactoryObjects_Create();
                Actor_Hammer_Create(object, ox + 24, oy);
            }

            // walker
            if (level_cells[x][y].object == ID_CELL_ENEMY_WALKER)
            {
                object = FactoryObjects_Create();
                Actor_Walker_Create(object, ox + 24, oy);
            }

            // circularsaw
            if (level_cells[x][y].object == ID_CELL_ENEMY_CIRCULARSAW)
            {
                object = FactoryObjects_Create();
                Actor_Circularsaw_Create(object, ox + 24, oy);
            }

            // tank
            if (level_cells[x][y].object == ID_CELL_ENEMY_TANK)
            {
                object = FactoryObjects_Create();
                Actor_Tank_Create(object, ox + 24, oy);
            }

            // gear
            if (level_cells[x][y].object == ID_CELL_GEAR)
            {
                object = FactoryObjects_Create();
                Actor_Gear_Create(object, ox + 24, oy + 24);
            }
        }
    }
}

void _Level_FillFog(void)
{
    unsigned int x = 0;
    unsigned int y = 0;

    for (y = 0; y < level_cells_height; ++y)
    for (x = 0; x < level_cells_width;  ++x)
    {
        level_cells[x][y].fog      = false;
        level_cells[x][y].fog_type = FOG_FILL;
    }

    for (y = 1; y < level_cells_height - 1; ++y)
    for (x = 1; x < level_cells_width  - 1;  ++x)
    {
        level_cells[x][y].fog      = true;
        level_cells[x][y].fog_type = FOG_FILL;
    }
}

void _Level_OpenFogInCell(const int cx, const int cy)
{
    if ((cx >= 0) && (cx < level_cells_width) &&
        (cy >= 0) && (cy < level_cells_height))
    {
        if (level_cells[cx][cy].fog)
            level_cells[cx][cy].fog = false;
    }
}

void _Level_CalculateFogCorners(void)
{
    unsigned int cx;
    unsigned int cy;

	for (cy = 0; cy < level_cells_height; ++cy)
    for (cx = 0; cx < level_cells_width;  ++cx)
    {
		if (level_cells[cx][cy].fog)
		{
			bool up    = false;
			bool right = false;
			bool down  = false;
			bool left  = false;

			const int ccx = cx;
			const int ccy = cy;
			// вверх
			if (ccy - 1 >= 0)
			{
				if (!level_cells[ccx][ccy - 1].fog)
                    up = true;
			}

			// вправо
			if (ccx + 1 < level_cells_width)
			{
				if (!level_cells[ccx + 1][ccy].fog)
                    right = true;
			}

			// вниз
			if (ccy + 1 < level_cells_height)
			{
				if (!level_cells[ccx][ccy + 1].fog)
                    down = true;
			}

			// влево
			if (ccx - 1 >= 0)
			{
				if (!level_cells[ccx - 1][ccy].fog)
                    left = true;
			}

			if ( up && right && down && left )     level_cells[cx][cy].fog_type = FOG_0;
			if ( up && !right && !down && !left )  level_cells[cx][cy].fog_type = FOG_1;
			if ( !up && right && !down && !left )  level_cells[cx][cy].fog_type = FOG_2;
			if ( !up && !right && down && !left )  level_cells[cx][cy].fog_type = FOG_3;
			if ( !up && !right && !down && left )  level_cells[cx][cy].fog_type = FOG_4;
			if ( !up && !right && !down && !left ) level_cells[cx][cy].fog_type = FOG_FILL;

			if ( up && right && !down && !left )   level_cells[cx][cy].fog_type = FOG_12;
			if ( up && !right && down && !left )   level_cells[cx][cy].fog_type = FOG_13;
			if ( up && !right && !down && left )   level_cells[cx][cy].fog_type = FOG_14;

			if ( !up && right && down && !left )   level_cells[cx][cy].fog_type = FOG_23;
			if ( !up && right && !down && left )   level_cells[cx][cy].fog_type = FOG_24;

			if ( !up && !right && down && left )   level_cells[cx][cy].fog_type = FOG_34;

			if ( up &&  right && !down &&  left)   level_cells[cx][cy].fog_type = FOG_124;
			if ( up &&  right &&  down && !left)   level_cells[cx][cy].fog_type = FOG_123;
			if (!up &&  right &&  down &&  left)   level_cells[cx][cy].fog_type = FOG_234;
			if ( up && !right &&  down &&  left)   level_cells[cx][cy].fog_type = FOG_134;
		}
	}
}

void Level_CreateEmpty(const int cells_width, const int cells_height)
{
    unsigned int i = 0;
    unsigned int x = 0;
    unsigned int y = 0;

    level_cells_width  = cells_width;
    level_cells_height = cells_height;
    level_width        = level_cells_width * CELL_WIDTH;
    level_height       = level_cells_width * CELL_HEIGHT;

    level_cells = (level_cells_t**) malloc(level_cells_width * sizeof(level_cells_t*));

    for (i = 0; i < level_cells_width; ++i)
    {
        level_cells[i] = (level_cells_t*) malloc(level_cells_height * sizeof(level_cells_t));
    }

    for (y = 0; y < level_cells_height; ++y)
    for (x = 0; x < level_cells_width; ++x)
    {
        level_cells[x][y].collision = 0;
        level_cells[x][y].object    = 0;
        level_cells[x][y].tile      = 0;
        level_cells[x][y].back      = 0;
    }

    Camera_SetLevelBounds(level_width, level_height);

    _Level_CreateObjects();
}

void Level_Create(const char *filename)
{
    level_cells_width  = 0;
    level_cells_height = 0;

    bool res = _Level_Load(filename);

    _Level_FillFog();

    Camera_SetLevelBounds(level_width, level_height);

    if (res)
        _Level_CreateObjects();
}

void Level_Destroy(void)
{
    unsigned int i = 0;

    for (i = 0; i < level_cells_width; ++i)
    {
        free(level_cells[i]);
    }

    free(level_cells);

    level_cells_width  = 0;
    level_cells_height = 0;
}

int Level_GetCellsWidth(void)
{
    return level_cells_width;
}

int Level_GetCellsHeight(void)
{
    return level_cells_height;
}

int Level_GetWidth(void)
{
    return level_width;
}

int Level_GetHeight(void)
{
    return level_height;
}

vector_t Level_GetPositionStart(void)
{
    unsigned int x;
    unsigned int y;
    vector_t result = Utils_GetVector(0, 0);

    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            if (level_cells[x][y].object == ID_CELL_ROBO_START)
            {
                result.x = x * CELL_WIDTH;
                result.y = y * CELL_HEIGHT;
            }
        }
    }

    return result;
}

void Level_OpenFogInPosition(vector_t position)
{
    int cx  = (int)(position.x / CELL_WIDTH);
    int cy  = (int)(position.y / CELL_HEIGHT);
	int icx = cx - 2;
	int icy = cy - 2;
	int x;
    int y;

    for (y = 0; y < 5; ++y)
	for (x = 0; x < 5; ++x)
	{
		_Level_OpenFogInCell(x + icx, y + icy);
	}

	_Level_OpenFogInCell(cx,     cy - 3);
	_Level_OpenFogInCell(cx - 1, cy - 3);
	_Level_OpenFogInCell(cx + 1, cy - 3);

	_Level_OpenFogInCell(cx + 3, cy    );
	_Level_OpenFogInCell(cx + 3, cy - 1);
	_Level_OpenFogInCell(cx + 3, cy + 1);

	_Level_OpenFogInCell(cx,     cy + 3);
	_Level_OpenFogInCell(cx - 1, cy + 3);
	_Level_OpenFogInCell(cx + 1, cy + 3);

	_Level_OpenFogInCell(cx - 3, cy    );
	_Level_OpenFogInCell(cx - 3, cy - 1);
	_Level_OpenFogInCell(cx - 3, cy + 1);

	_Level_CalculateFogCorners();
}

bool Level_CheckCollision(object_info_t info, vector_t velocity, bool horizonatal, float *correct_value)
{
    bool result = false;

    unsigned int x = 0;
    unsigned int y = 0;
    SDL_Rect     cell_rect = Utils_GetRect(0, 0, CELL_WIDTH, CELL_HEIGHT);
    SDL_Rect     intersect_rect;

    *correct_value = 0;

    point_t coll_ul = info.collision_cell_ul;
    point_t coll_br = info.collision_cell_br;

    // guard massive
    if (coll_ul.x < 0)
        coll_ul.x = 0;

    if (coll_ul.y < 0)
        coll_ul.y = 0;

    if (coll_ul.x >= level_cells_width - 1)
        coll_ul.x = level_cells_width - 1;

    if (coll_ul.y >= level_cells_height - 1)
        coll_ul.y = level_cells_height - 1;

    if (coll_br.x < 0)
        coll_br.x = 0;

    if (coll_br.y < 0)
        coll_br.y = 0;

    if (coll_br.x >= level_cells_width - 1)
        coll_br.x = level_cells_width - 1;

    if (coll_br.y >= level_cells_height - 1)
        coll_br.y = level_cells_height - 1;

    for (y = coll_ul.y; y <= coll_br.y; ++y)
    {
        for (x = coll_ul.x; x <= coll_br.x; ++x)
        {
            cell_rect.x = (x * CELL_WIDTH);
            cell_rect.y = (y * CELL_HEIGHT);

            // block
            if (level_cells[x][y].collision == ID_CELL_COLLISION_BLOCK)
            {
                if (SDL_IntersectRect(&info.collision_rect, &cell_rect, &intersect_rect))
                {
                    float offset;

                    if (horizonatal)
                    {
                        // right
                        if (velocity.x > 0)
                        {
                            if (info.position.x > (info.collision_rect.x + info.collision_rect.w))
                                 offset = info.position.x - (info.collision_rect.x + info.collision_rect.w);
                            else offset = (info.collision_rect.x + info.collision_rect.w) - info.position.x;

                            *correct_value = cell_rect.x - offset;

                            result = true;
                        }

                        // left
                        if (velocity.x < 0)
                        {
                            if (info.position.x > info.collision_rect.x)
                                 offset = info.position.x - info.collision_rect.x;
                            else offset = info.collision_rect.x - info.position.x;

                            *correct_value = cell_rect.x + CELL_WIDTH + offset;

                            result = true;
                        }
                    }
                    else
                    {
                        if (velocity.y > 0)
                        {
                            // down
                            if (info.position.y > (info.collision_rect.y + info.collision_rect.h))
                                 offset = info.position.y - (info.collision_rect.y + info.collision_rect.h);
                            else offset = (info.collision_rect.y + info.collision_rect.h) - info.position.y;

                            *correct_value = cell_rect.y - offset;

                            result = true;
                        }

                        if (velocity.y < 0)
                        {
                            // up
                            if (info.position.y > info.collision_rect.y)
                                 offset = info.position.y - info.collision_rect.y;
                            else offset = info.collision_rect.y - info.position.y;

                            *correct_value = cell_rect.y + CELL_HEIGHT + offset;

                            result = true;
                        }
                    }
                }
            }

            //bridge
            if (level_cells[x][y].collision == ID_CELL_COLLISION_BRIDGE)
            {
                if (SDL_IntersectRect(&info.collision_rect, &cell_rect, &intersect_rect))
                {
                    float offset;

                    if (!horizonatal)
                    {
                        if (velocity.y > 0)
                        {
                            // down
                            if (info.position.y > (info.collision_rect.y + info.collision_rect.h))
                                 offset = info.position.y - (info.collision_rect.y + info.collision_rect.h);
                            else offset = (info.collision_rect.y + info.collision_rect.h) - info.position.y;

                            float pos_y = info.position.y + (offset-6);
                            if (pos_y < cell_rect.y)
                            {
                                *correct_value = cell_rect.y - offset;

                                result = true;
                            }
                        }
                    }
                }
            }
        }
    }

    return result;
}

bool Level_CheckTurn(object_info_t info, bool *right)
{
    bool result = false;

    unsigned int x = 0;
    unsigned int y = 0;
    SDL_Rect     cell_rect = Utils_GetRect(0, 0, CELL_WIDTH, CELL_HEIGHT);
    SDL_Rect     intersect_rect;

    *right = false;

    point_t coll_ul = info.collision_cell_ul;
    point_t coll_br = info.collision_cell_br;

    // guard massive
    if (coll_ul.x < 0)
        coll_ul.x = 0;

    if (coll_ul.y < 0)
        coll_ul.y = 0;

    if (coll_ul.x >= level_cells_width - 1)
        coll_ul.x = level_cells_width - 1;

    if (coll_ul.y >= level_cells_height - 1)
        coll_ul.y = level_cells_height - 1;

    if (coll_br.x < 0)
        coll_br.x = 0;

    if (coll_br.y < 0)
        coll_br.y = 0;

    if (coll_br.x >= level_cells_width - 1)
        coll_br.x = level_cells_width - 1;

    if (coll_br.y >= level_cells_height - 1)
        coll_br.y = level_cells_height - 1;

    for (y = coll_ul.y; y <= coll_br.y; ++y)
    {
        for (x = coll_ul.x; x <= coll_br.x; ++x)
        {
            cell_rect.x = (x * CELL_WIDTH);
            cell_rect.y = (y * CELL_HEIGHT);

            if (level_cells[x][y].collision == ID_CELL_TURN_RIGHT)
            {
                if (SDL_IntersectRect(&info.collision_rect, &cell_rect, &intersect_rect))
                {
                    *right = true;
                    result = true;
                }
            }

            if (level_cells[x][y].collision == ID_CELL_TURN_LEFT)
            {
                if (SDL_IntersectRect(&info.collision_rect, &cell_rect, &intersect_rect))
                {
                    *right = false;
                    result = true;
                }
            }
        }
    }

    return result;
}

void Level_DrawCollisions(SDL_Renderer *renderer)
{
    unsigned int x = 0;
    unsigned int y = 0;
    SDL_Rect     frame_rect;
    SDL_Rect     draw_rect;

    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            if (level_cells[x][y].collision != 0)
            {
                point_t frame_pos =  Utils_GetPositionFrame(level_cells[x][y].collision-1, 96, CELL_FRAME_WIDTH);

                frame_rect = Utils_GetRect(frame_pos.x*CELL_FRAME_WIDTH, frame_pos.y*CELL_FRAME_HEIGHT, CELL_FRAME_WIDTH, CELL_FRAME_HEIGHT);
                draw_rect  = Utils_GetRect((x * CELL_WIDTH), (y * CELL_HEIGHT), CELL_WIDTH, CELL_HEIGHT);

                Camera_Draw(renderer, tilesTex, &frame_rect, &draw_rect);
            }
        }
    }
}

void Level_DrawObjects(SDL_Renderer *renderer)
{
}

void Level_DrawTiles(SDL_Renderer *renderer)
{
    unsigned int x = 0;
    unsigned int y = 0;
    point_t      frame_position;
    SDL_Rect     frame_rect;
    SDL_Rect     draw_rect;

    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            if (level_cells[x][y].tile != 0)
            {
                frame_position = Utils_GetPositionFrame(level_cells[x][y].tile - 1, TEXTURE_TILES_WIDTH, CELL_FRAME_WIDTH);

                frame_rect = Utils_GetRect((frame_position.x * CELL_FRAME_WIDTH), (frame_position.y * CELL_FRAME_HEIGHT), CELL_FRAME_WIDTH, CELL_FRAME_HEIGHT);
                draw_rect  = Utils_GetRect((x * CELL_WIDTH), (y * CELL_HEIGHT), CELL_WIDTH, CELL_HEIGHT);

                Camera_Draw(renderer, tilesTex, &frame_rect, &draw_rect);
            }
        }
    }
}

void Level_DrawBack(SDL_Renderer *renderer)
{
    unsigned int x = 0;
    unsigned int y = 0;
    point_t      frame_position;
    SDL_Rect     frame_rect;
    SDL_Rect     draw_rect;

    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            if (level_cells[x][y].back != 0)
            {
                frame_position = Utils_GetPositionFrame(level_cells[x][y].back - 1, TEXTURE_TILES_WIDTH, CELL_FRAME_WIDTH);

                frame_rect = Utils_GetRect((frame_position.x * CELL_FRAME_WIDTH), (frame_position.y * CELL_FRAME_HEIGHT), CELL_FRAME_WIDTH, CELL_FRAME_HEIGHT);
                draw_rect  = Utils_GetRect((x * CELL_WIDTH), (y * CELL_HEIGHT), CELL_WIDTH, CELL_HEIGHT);

                Camera_Draw(renderer, tilesTex, &frame_rect, &draw_rect);
            }
        }
    }
}

void Level_DrawFog(SDL_Renderer *renderer)
{
    unsigned int x = 0;
    unsigned int y = 0;
    SDL_Rect     frame_rect;
    SDL_Rect     draw_rect;

    for (y = 0; y < level_cells_height; ++y)
    {
        for (x = 0; x < level_cells_width; ++x)
        {
            if (level_cells[x][y].fog)
            {
                frame_rect = Utils_GetRect(0, 0, CELL_FRAME_WIDTH, CELL_FRAME_HEIGHT);
                draw_rect  = Utils_GetRect((x * CELL_WIDTH), (y * CELL_HEIGHT), CELL_WIDTH, CELL_HEIGHT);

                switch(level_cells[x][y].fog_type)
                {
                    case FOG_FILL : frame_rect.x = 0;  frame_rect.y = 0;  break;
                    case FOG_0    : frame_rect.x = 16; frame_rect.y = 0;  break;
                    case FOG_1    : frame_rect.x = 32; frame_rect.y = 0;  break;
                    case FOG_2    : frame_rect.x = 48; frame_rect.y = 0;  break;
                    case FOG_3    : frame_rect.x = 0;  frame_rect.y = 16; break;
                    case FOG_4    : frame_rect.x = 16; frame_rect.y = 16; break;
                    case FOG_12   : frame_rect.x = 32; frame_rect.y = 16; break;
                    case FOG_13   : frame_rect.x = 48; frame_rect.y = 16; break;
                    case FOG_14   : frame_rect.x = 0;  frame_rect.y = 32; break;
                    case FOG_23   : frame_rect.x = 16; frame_rect.y = 32; break;
                    case FOG_24   : frame_rect.x = 32; frame_rect.y = 32; break;
                    case FOG_34   : frame_rect.x = 48; frame_rect.y = 32; break;
                    case FOG_123  : frame_rect.x = 0;  frame_rect.y = 48; break;
                    case FOG_124  : frame_rect.x = 16; frame_rect.y = 48; break;
                    case FOG_234  : frame_rect.x = 32; frame_rect.y = 48; break;
                    case FOG_134  : frame_rect.x = 48; frame_rect.y = 48; break;
                }

                Camera_Draw(renderer, fogTex, &frame_rect, &draw_rect);
            }
        }
    }
}
