/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#pragma once
#include "../libs.h"
#include "player.h"
#include "card.h"
#include "render.h"

#include "../display/camera.h"
#include "../display/shader.h"
#include "../display/texture.h"
#include "../display/tileset.h"
#include "../display/framebuffer.h"

/** Rounds that the game can be in */
#define POKER_ROUND_MATCH 0x00
#define POKER_ROUND_START 0x01
#define POKER_ROUND_BLINDS 0x02
#define POKER_ROUND_DEAL 0x03
#define POKER_ROUND_BET0 0x04
#define POKER_ROUND_FLOP 0X05
#define POKER_ROUND_BET1 0x06
#define POKER_ROUND_TURN 0x07
#define POKER_ROUND_BET2 0x08
#define POKER_ROUND_RIVER 0x09
#define POKER_ROUND_BET3 0x0A
#define POKER_ROUND_WINNER 0x0B

/** How many cards the dealer can hold in their hand */
#define POKER_DEALER_HAND 5

/** How many cards the grave can hold */
#define POKER_GRAVE_SIZE CARD_DECK_SIZE

/** How many players in a poker game (excludes dealer) */
#define POKER_PLAYER_COUNT 5

/** How many chips each player has by defautl */
#define POKER_PLAYER_CHIPS_DEFAULT 10000

/** The default blind cost for the big blind. Small Blind is half this */
#define POKER_BLIND_BIG_DEFAULT 600
#define POKER_BLIND_SMALL_DEFAULT (POKER_BLIND_BIG_DEFAULT/2)

/** GUI Height fix (To keep gui scaling nicely we use a fixed height) */
#define POKER_GUI_HEIGHT 2160

/** How many cards to deal each player during the deal round */
#define POKER_DEAL_CARD_EACH 2

#define POKER_FLOP_CARD_COUNT 3
#define POKER_TURN_CARD_COUNT 1
#define POKER_RIVER_CARD_COUNT 1

/** Winning Types */
#define POKER_WINNING_TYPE_NULL 0x00
#define POKER_WINNING_TYPE_ROYAL_FLUSH 0x01
#define POKER_WINNING_TYPE_STRAIGHT_FLUSH 0x02
#define POKER_WINNING_TYPE_FOUR_OF_A_KIND 0x03
#define POKER_WINNING_TYPE_FULL_HOUSE 0x04
#define POKER_WINNING_TYPE_FLUSH 0x05
#define POKER_WINNING_TYPE_STRAIGHT 0x06
#define POKER_WINNING_TYPE_THREE_OF_A_KIND 0x07
#define POKER_WINNING_TYPE_TWO_PAIR 0x08
#define POKER_WINNING_TYPE_PAIR 0x09
#define POKER_WINNNIG_TYPE_HIGH_CARD 0x0A

/** How many cards make a winning set */
#define POKER_WINNING_SET_SIZE 5

/** Holds information about the winning player state */
typedef struct {
  /** The full set of both the dealer and player's hand */
  card_t full[POKER_PLAYER_HAND + POKER_DEALER_HAND];
  uint8_t fullSize;
  
  /** Holds the winning set */
  card_t set[POKER_WINNING_SET_SIZE];
  uint8_t setSize;

  /** Winning Type */
  uint8_t type;

  /** If there was a kicker card it will be here, otherwise -1 for no kicker */
  card_t kicker;
} pokerwinning_t;

typedef struct {
  //////////////////////////////////////////////////////////////////////////////
  // Poker Logic Variables
  //////////////////////////////////////////////////////////////////////////////
  
  /** Current Card Deck */
  card_t deck[CARD_DECK_SIZE];
  uint8_t deckSize;

  /** Card grave (where spent cards go when burned */
  card_t grave[POKER_GRAVE_SIZE];
  uint8_t graveSize;

  /** Blinds */
  uint32_t blindSmall, blindBig;

  /** Dealer Hand */
  card_t cards[POKER_DEALER_HAND];
  uint8_t cardsFacing;

  /** Player States */
  pokerplayer_t players[POKER_PLAYER_COUNT];

  /** Winning States */
  pokerwinning_t winnings[POKER_PLAYER_COUNT];
  uint8_t winners[POKER_PLAYER_COUNT];
  uint8_t winnerCount;

  /** The current round the game is on */
  uint8_t round;

  /** The current player that is the dealer */
  uint8_t roundDealer;
  uint8_t roundSmallBlind;
  uint8_t roundBigBlind;

  /** Current pot of chips */
  uint32_t pot;

  //////////////////////////////////////////////////////////////////////////////
  // Round variables
  //////////////////////////////////////////////////////////////////////////////
  uint32_t roundTextCounter;

  /** For Betting round, which player is currently betting */
  uint8_t roundBetCurrent;

  //////////////////////////////////////////////////////////////////////////////
  // Rendering Variables
  //////////////////////////////////////////////////////////////////////////////

  /** Frames to hold the world and GUI render outputs */
  framebuffer_t frameWorld, frameGui;
  /** Game's Font */
  font_t font;
  /** Game's Shader */
  shader_t shader;
  /** Camera for the world and the GUI */
  camera_t cameraWorld, cameraGui, cameraTest;

  /** Refer to POKER_GUI_HEIGHT */
  float guiWidth;

  /** Last frame's GUI width, used to track font wrapping */
  float textLastWidth;
  /** Primitive to hold talking text */
  primitive_t talkPrimitive;
  /** Current spoken text, tracked in-case of re-render */
  char *talkText;
  /** Information about the current rendered text */
  fonttextinfo_t *talkTextInfo;

  /** Match Scene Variables */
  float matchStart;








  texture_t dealerTexture;
  tileset_t dealerTileset;
  primitive_t dealerPrimitive;

  texture_t chipTexture;
  primitive_t chipPrimitive;
  
  texture_t tableTexture;
  primitive_t tablePrimitive;

  texture_t cardTexture;
  tileset_t cardTileset;
  primitive_t cardPrimitive;
} poker_t;