#include "../player.h"
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_keycode.h>
#include <stdio.h>

// @Todo: move/extern these so the npc/bandit can use them
//
#define G_OUTFIT_COMPONENT_COUNT 8

global_var Str8 __outfit_names[] = {
	Sl("npc_%s_base_%d"),
	Sl("npc_%s_eyes_%d"),
	Sl("npc_%s_face_%d"),
	Sl("npc_%s_hair_%d"),
	Sl("npc_%s_hat_%d"),
	Sl("npc_%s_shirt_%d"),
	Sl("npc_%s_shoes_%d"),
	Sl("npc_%s_trousers_%d")
};

global_var U32 __outfit_counts[] = {
	2, // base
	3, // eyes
	5, // face
	4, // hair
	3, // hat
	2, // shirt
	1, // shoes
	2  // trousers
};

global_var U32 __outfit_back_counts[] = {
	2, // base
	0, // eyes
	3, // face
	4, // hair
	3, // hat
	2, // shirt
	1, // shoes
	2  // trousers
};

StaticAssert(ArraySize(__outfit_names) == ArraySize(__outfit_counts));

#define OUTFIT_IMG(dir, n) D_ImageHandle(&game->draw, Sf(temp.arena, (const char *) __outfit_names[it].data, #dir, n))

void PlayerInit(G_State *game, Player *player) {
	World *world  = game->world;
	player->world = world;

	world->player.bulletsLoaded = PLAYER_BULLET_COUNT;
	world->player.currentArea = WORLD_AREA_OUTSIDE;

	G_Outfit *outfit = &player->outfit;

	D_AnimationInit(&outfit->state, 0, 1, 4, 1.0f / 6.0f);

	M_TempScope(0, 0) {
		for (U32 it = 0; it < G_OUTFIT_COMPONENT_COUNT; ++it) {
			U32 idx = Random_Next(&world->random) % __outfit_counts[it];

			// We just allow face, hair and hat to default to 0 meaning the player doesn't have one
			if (idx != 0 || it < 2 || it > 4) {
				outfit->front.e[it] = OUTFIT_IMG(front, idx);
				outfit->side.e[it]  = OUTFIT_IMG(side,  idx);

				if ((idx + 1) <= __outfit_counts[it]) {
					outfit->back.e[it]  = OUTFIT_IMG(back, idx);
				}
			}
		}
	}
}

void PlayerInput(SDL_Event *event, Player *player)
{
  SDL_KeyboardEvent key = event->key;
  SDL_MouseButtonEvent mouseBtn = event->button;
  if(event->type == SDL_EVENT_KEY_DOWN || event->type == SDL_EVENT_KEY_UP) {
    bool val = event->type == SDL_EVENT_KEY_DOWN;
    switch (key.key)
    {
      case SDLK_W:
      {
        player->controls.upDown = val;
        break;
      }
      case SDLK_A:
      {
        player->controls.leftDown = val;
        break;
      }
      case SDLK_D:
      {
        player->controls.rightDown = val;
        break;
      }
      case SDLK_S:
      {
        player->controls.downDown = val;
        break;
      }
    }
  }
  if (
    event->type == SDL_EVENT_MOUSE_BUTTON_DOWN
    && mouseBtn.button == SDL_BUTTON_LEFT
  ) {
    if(player->bulletsLoaded > 0) {
      // shooting
      player->bulletsLoaded -= 1;
      player->controls.shot = true;
      player->shotPos = player->world->mouseProjected;
      printf("shot %f %f\n", player->shotPos.x, player->shotPos.y);
    } else if(player->reloadTimer == 0) {
      player->reloadTimer = PLAYER_RELOAD_TIME;
      printf("reloading\n");
  };
  }
}

void PlayerUpdate(F32 delta, Player *player) {
  player->controls.shot = false;
  V2f dir = V2F(0, 0);
  if(player->controls.upDown) {
    dir.y -= 1;
		player->outfit.dir = G_OUTFIT_DIR_BACK;
  }
  if(player->controls.downDown) {
    dir.y += 1;
		player->outfit.dir = G_OUTFIT_DIR_FRONT;
  }
  if(player->controls.leftDown) {
    dir.x -= 1;
		player->outfit.dir = G_OUTFIT_DIR_SIDE | G_OUTFIT_DIR_FLIPPED;
  }
  if(player->controls.rightDown) {
    dir.x += 1;
		player->outfit.dir = G_OUTFIT_DIR_SIDE;
  }

	if (dir.x != 0 || dir.y != 0) {
		D_AnimationUpdate(&player->outfit.state, delta);
	}
	else {
		player->outfit.state.index = 0;
	}

  if(player->reloadTimer > 0) {
    player->reloadTimer-=delta;
    if(player->reloadTimer <= 0) {
      player->bulletsLoaded = PLAYER_BULLET_COUNT;
      player->reloadTimer = 0;
    }
  }
  dir = V2f_Scale(NormaliseV2F(dir), PLAYER_SPEED*delta);
  player->pos.x += dir.x;
  player->pos.y += dir.y;
}

void PlayerDraw(D_Context *draw, Player *player) {
	G_Outfit *outfit = &player->outfit;

	R2f pframe = D_AnimationFrame(&outfit->state);

	for (U32 it = 0; it < G_OUTFIT_COMPONENT_COUNT; ++it) {
		U32 flipped = (outfit->dir & G_OUTFIT_DIR_FLIPPED) != 0;
		U32 dir = (outfit->dir & ~G_OUTFIT_DIR_FLIPPED);

		U32 tid = outfit->e[dir].e[it];
		if (tid != 0) {
			U32 flags = D_RECT_UV_ASPECT | (flipped ? D_RECT_FLIP_X : 0);
			D_Rect(draw, player->pos.x, player->pos.y, .texture = tid, .uv = pframe, .flags = flags);
		}
	}
}
