#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <raylib.h>

#include "dialog.h"

Dialog dialogs[6];

void handle_click_cancel_yes(Game *g) {
  g->player.dekiyaku_action = DEKIYAKU_ACTION_CANCEL;
  g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
}

void handle_click_cancel_no(Game *g) {
  g->state = GAME_STATE_CHOOSING_FROM_HAND;
}

void handle_click_shoubu(Game *g) {
  g->player.dekiyaku_action = DEKIYAKU_ACTION_SHOUBU;
  g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
}

void handle_click_sage(Game *g) {
  g->player.dekiyaku_action = DEKIYAKU_ACTION_SAGE;
  g->turn_number++;
  g->state = GAME_STATE_CHOOSING_FROM_HAND;
}

void handle_click_ok_end_of_round(Game *g) {
  g->state = GAME_STATE_END_OF_ROUND;
}

void handle_click_ok_end_of_game(Game *g) {
  g->state = GAME_STATE_TITLE_SCREEN;
}

void handle_click_play_again(Game *g) {
  g->state = GAME_STATE_NEW_GAME;
}

void handle_click_quit(Game *g) {
  g->should_close = true;
}

void handle_click_claim_set_teyaku(Game *g) {
  g->player.teyaku.chaff = CHAFF_TEYAKU_NONE;
  teyaku_to_string(&g->player.teyaku, g->player.teyaku_string);
  g->state = GAME_STATE_START_OF_TURN;
}

void handle_click_claim_chaff_teyaku(Game *g) {
  g->player.teyaku.set = SET_TEYAKU_NONE;
  teyaku_to_string(&g->player.teyaku, g->player.teyaku_string);
  g->state = GAME_STATE_START_OF_TURN;
}

void handle_click_claim_both_teyaku(Game *g) {
  g->state = GAME_STATE_START_OF_TURN;
}

void handle_click_dont_claim_teyaku(Game *g) {
  (&g->player.teyaku)->chaff = CHAFF_TEYAKU_NONE;
  g->player.teyaku.set = SET_TEYAKU_NONE;
  teyaku_to_string(&g->player.teyaku, g->player.teyaku_string);
  g->state = GAME_STATE_START_OF_TURN;
}

void init_dialogs(Game *g) {
  Dialog *cancel_dialog = &dialogs[0];
  cancel_dialog->text_count = 1;
  cancel_dialog->text[0] = malloc(200);
  strcpy(cancel_dialog->text[0], "Would you like to cancel?");
  cancel_dialog->text_color = BLACK;
  cancel_dialog->options_count = 2;
  cancel_dialog->game = g;

  cancel_dialog->options[0].text = malloc(50);
  strcpy(cancel_dialog->options[0].text, "Yes");
  cancel_dialog->options[0].color = GREEN;
  cancel_dialog->options[0].handle = &handle_click_cancel_yes;

  cancel_dialog->options[1].text = malloc(50);
  strcpy(cancel_dialog->options[1].text, "No");
  cancel_dialog->options[1].color = RED;
  cancel_dialog->options[1].handle = &handle_click_cancel_no;

  Dialog *shoubu_dialog = &dialogs[1];
  shoubu_dialog->text_count = 1;
  shoubu_dialog->text[0] = malloc(200);
  strcpy(shoubu_dialog->text[0], "You have dekiyaku! Sage or shoubu?");
  shoubu_dialog->text_color = BLACK;
  shoubu_dialog->options_count = 2;
  shoubu_dialog->game = g;

  shoubu_dialog->options[0].text = malloc(50);
  strcpy(shoubu_dialog->options[0].text, "Sage");
  shoubu_dialog->options[0].color = GREEN;
  shoubu_dialog->options[0].handle = &handle_click_sage;

  shoubu_dialog->options[1].text = malloc(50);
  strcpy(shoubu_dialog->options[1].text, "Shoubu");
  shoubu_dialog->options[1].color = RED;
  shoubu_dialog->options[1].handle = &handle_click_shoubu;

  Dialog *no_dekiyaku_end_of_round_dialog = &dialogs[2];
  no_dekiyaku_end_of_round_dialog->text_count = 3;
  no_dekiyaku_end_of_round_dialog->text[0] = malloc(200);
  no_dekiyaku_end_of_round_dialog->text[1] = malloc(200);
  no_dekiyaku_end_of_round_dialog->text[2] = malloc(200);
  strcpy(no_dekiyaku_end_of_round_dialog->text[0], "Player score");
  strcpy(no_dekiyaku_end_of_round_dialog->text[1], "Right score");
  strcpy(no_dekiyaku_end_of_round_dialog->text[2], "Left score");
  no_dekiyaku_end_of_round_dialog->text_color = BLACK;
  no_dekiyaku_end_of_round_dialog->options_count = 1;
  no_dekiyaku_end_of_round_dialog->game = g;

  no_dekiyaku_end_of_round_dialog->options[0].text = malloc(50);
  strcpy(no_dekiyaku_end_of_round_dialog->options[0].text, "Okay");
  no_dekiyaku_end_of_round_dialog->options[0].color = GREEN;
  no_dekiyaku_end_of_round_dialog->options[0].handle = &handle_click_ok_end_of_round;

  Dialog *end_of_game_dialog = &dialogs[3];
  end_of_game_dialog->text_count = 4;
  end_of_game_dialog->text[0] = malloc(200);
  end_of_game_dialog->text[1] = malloc(200);
  end_of_game_dialog->text[2] = malloc(200);
  end_of_game_dialog->text[3] = malloc(200);
  end_of_game_dialog->text_color = BLACK;
  end_of_game_dialog->options_count = 2;
  end_of_game_dialog->game = g;

  end_of_game_dialog->options[0].text = malloc(50);
  strcpy(end_of_game_dialog->options[0].text, "Play Again");
  end_of_game_dialog->options[0].color = GREEN;
  end_of_game_dialog->options[0].handle = &handle_click_play_again;
  end_of_game_dialog->options[1].text = malloc(50);
  strcpy(end_of_game_dialog->options[1].text, "Quit");
  end_of_game_dialog->options[1].color = GREEN;
  end_of_game_dialog->options[1].handle = &handle_click_quit;

  Dialog *dekiyaku_end_of_round_dialog = &dialogs[4];
  dekiyaku_end_of_round_dialog->text_count = 3;
  dekiyaku_end_of_round_dialog->text[0] = malloc(200);
  dekiyaku_end_of_round_dialog->text[1] = malloc(200);
  dekiyaku_end_of_round_dialog->text[2] = malloc(200);
  strcpy(dekiyaku_end_of_round_dialog->text[0], "Player score");
  strcpy(dekiyaku_end_of_round_dialog->text[1], "Right score");
  strcpy(dekiyaku_end_of_round_dialog->text[2], "Left score");
  dekiyaku_end_of_round_dialog->text_color = BLACK;
  dekiyaku_end_of_round_dialog->options_count = 1;
  dekiyaku_end_of_round_dialog->game = g;

  dekiyaku_end_of_round_dialog->options[0].text = malloc(50);
  strcpy(dekiyaku_end_of_round_dialog->options[0].text, "Okay");
  dekiyaku_end_of_round_dialog->options[0].color = GREEN;
  dekiyaku_end_of_round_dialog->options[0].handle = &handle_click_ok_end_of_round;

  Dialog *teyaku_dialog = &dialogs[5];
  teyaku_dialog->text_count = 3;
  teyaku_dialog->text[0] = malloc(200);
  teyaku_dialog->text[1] = malloc(200);
  teyaku_dialog->text[2] = malloc(200);
  strcpy(teyaku_dialog->text[0], "You can claim some teyaku");
  teyaku_dialog->text_color = BLACK;
  teyaku_dialog->options_count = 4;
  teyaku_dialog->game = g;

  teyaku_dialog->options[0].text = malloc(50);
  strcpy(teyaku_dialog->options[0].text, "Claim Set Teyaku");
  teyaku_dialog->options[0].color = SKYBLUE;
  teyaku_dialog->options[0].handle = &handle_click_claim_set_teyaku;

  teyaku_dialog->options[1].text = malloc(50);
  strcpy(teyaku_dialog->options[1].text, "Claim Chaff Teyaku");
  teyaku_dialog->options[1].color = SKYBLUE;
  teyaku_dialog->options[1].handle = &handle_click_claim_chaff_teyaku;
  
  teyaku_dialog->options[2].text = malloc(50);
  strcpy(teyaku_dialog->options[2].text, "Claim Both Teyaku");
  teyaku_dialog->options[2].color = GREEN;
  teyaku_dialog->options[2].handle = &handle_click_claim_both_teyaku;

  teyaku_dialog->options[3].text = malloc(50);
  strcpy(teyaku_dialog->options[3].text, "Don't Claim");
  teyaku_dialog->options[3].color = RED;
  teyaku_dialog->options[3].handle = &handle_click_dont_claim_teyaku;
}

void cancel_dialog(Game *g) { g->dialog = &dialogs[0]; }
void shoubu_dialog(Game *g) { g->dialog = &dialogs[1]; }
void no_dekiyaku_end_of_round_dialog(Game *g) { g->dialog = &dialogs[2]; }
void end_of_game_dialog(Game *g) { g->dialog = &dialogs[3]; }
void dekiyaku_end_of_round_dialog(Game *g) { g->dialog = &dialogs[4]; }
void teyaku_dialog(Game *g) { g->dialog = &dialogs[5]; }

Rectangle dialog_option_outer_rectangle(Dialog *d, int i) {
  if (d->options_count < 4) {
    return (Rectangle) {
      ((960 * (i + 1)) / (d->options_count + 1)) - 10 + 200,
      500,
      MeasureText(d->options[i].text, DIALOG_OPTION_FONT_SIZE) + 20,
      40,
    };
  } else {
    return (Rectangle) {
      ((960 * (i % 2)) / ((d->options_count / 2) + 1)) - 10 + 250,
      500 + ((i / 2) * 50),
      MeasureText(d->options[i].text, DIALOG_OPTION_FONT_SIZE) + 20,
      40,
    };
  }
}

Rectangle dialog_option_inner_rectangle(Dialog *d, int i) {
  Rectangle outer = dialog_option_outer_rectangle(d, i);
  return (Rectangle) {
    outer.x + 3,
    outer.y + 3,
    outer.width - 6,
    outer.height - 6,
  };
}

void dialog_draw(Dialog *d) {
  int text_width;
  DrawRectangleRec(DIALOG_OUTER_RECTANGLE, BLACK);
  DrawRectangleRec(DIALOG_INNER_RECTANGLE, WHITE);

  for (int i = 0; i < d->text_count; i++) {
    text_width = MeasureText(d->text[i], DIALOG_TEXT_FONT_SIZE);
    DrawText(d->text[i], 700 - (text_width / 2), 300 + (70 * (i - 1)), DIALOG_TEXT_FONT_SIZE, d->text_color);
  }

  for (int i = 0; i < d->options_count; i++) {
    DialogOption *o = &d->options[i];
    Rectangle outer = dialog_option_outer_rectangle(d, i);
    Rectangle inner = dialog_option_inner_rectangle(d, i);
    DrawRectangleRec(outer, BLACK);
    DrawRectangleRec(inner, o->color);
    DrawText(o->text, inner.x + 3, inner.y + 3, DIALOG_OPTION_FONT_SIZE, BLACK);
  }
}

void dialog_handle_input(Dialog *d) {
  if (IsMouseButtonPressed(0)) {
    Vector2 mouse_pos = GetMousePosition();
    for (int i = 0; i < d->options_count; i++) {
      DialogOption *o = &d->options[i];
      Rectangle outer = dialog_option_outer_rectangle(d, i);
      if (CheckCollisionPointRec(mouse_pos, outer)) {
	o->handle(d->game);
	d->game->dialog = NULL;
	break;
      }
    }
  }
}