=begin

 Reminders:

 - Hashes: Collection of unique keys and their corresponding values. The values can be found
   using their keys.

   In this sample app, the decisions needed for the game are stored in a hash. In fact, the
   decision.rb file contains hashes inside of other hashes!

   Each option is a key in the first hash, but also contains a hash (description and
   decision being its keys) as its value.
   Go into the decision.rb file and take a look before diving into the code below.

 - args.outputs.labels: An array. The values generate a label.
   The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
   For more information about labels, go to mygame/documentation/02-labels.md.

 - args.keyboard.key_down.KEY: Determines if a key is in the down state or pressed down.
   For more information about the keyboard, go to mygame/documentation/06-keyboard.md.

 - String interpolation: uses #{} syntax; everything between the #{ and the } is evaluated
   as Ruby code, and the placeholder is replaced with its corresponding value or result.

=end

# This sample app provides users with a story and multiple decisions that they can choose to make.
# Users can make a decision using their keyboard, and the story will move forward based on user choices.

# The decisions available to users are stored in the decision.rb file.
# We must have access to it for the game to function properly.
GAME_FILE = 'app/decision.rb' # found in app folder

require GAME_FILE # require used to load another file, import class/method definitions

# Instructions are given using labels to users if they have not yet set up their story in the decision.rb file.
# Otherwise, the game is run.
def tick args
  if !args.state.loaded && !respond_to?(:game) # if game is not loaded and not responding to game symbol's method
    args.labels << [640, 370, 'Hey there! Welcome to Four Decisions.', 0, 1] # a welcome label is shown
    args.labels << [640, 340, 'Go to the file called decision.rb and tell me your story.', 0, 1]
  elsif respond_to?(:game) # otherwise, if responds to game
    args.state.loaded = true
    tick_game args # calls tick_game method, runs game
  end

  if Kernel.tick_count.mod_zero? 60 # update every 60 frames
    t = GTK.ffi_file.mtime GAME_FILE # mtime returns modification time for named file
    if t != args.state.mtime
      args.state.mtime = t
      require GAME_FILE # require used to load file
      args.state.game_definition = nil # game definition and decision are empty
      args.state.decision_id = nil
    end
  end
end

# Runs methods needed for game to function properly
# Creates a rectangular border around the screen
def tick_game args
  defaults args
  args.borders << args.grid.rect
  render_decision args
  process_inputs args
end

# Sets default values and uses decision.rb file to define game and decision_id
# variable using the starting decision
def defaults args
  args.state.game_definition ||= game
  args.state.decision_id ||= args.state.game_definition[:starting_decision]
end

# Outputs the possible decision descriptions the user can choose onto the screen
# as well as what key to press on their keyboard to make their decision
def render_decision args
  decision = current_decision args
  # text is either the value of decision's description key or warning that no description exists
  args.labels << [640, 360, decision[:description] || "No definition found for #{args.state.decision_id}. Please update decision.rb.", 0, 1] # uses string interpolation

  # All decisions are stored in a hash
  # The descriptions output onto the screen are the values for the description keys of the hash.
  if decision[:option_one]
    args.labels << [10, 360, decision[:option_one][:description], 0, 0] # option one's description label
    args.labels << [10, 335, "(Press 'left' on the keyboard to select this decision)", -5, 0] # label of what key to press to select the decision
  end

  if decision[:option_two]
    args.labels << [1270, 360, decision[:option_two][:description], 0, 2] # option two's description
    args.labels << [1270, 335, "(Press 'right' on the keyboard to select this decision)", -5, 2]
  end

  if decision[:option_three]
    args.labels << [640, 45, decision[:option_three][:description], 0, 1] # option three's description
    args.labels << [640, 20, "(Press 'down' on the keyboard to select this decision)", -5, 1]
  end

  if decision[:option_four]
    args.labels << [640, 700, decision[:option_four][:description], 0, 1] # option four's description
    args.labels << [640, 675, "(Press 'up' on the keyboard to select this decision)", -5, 1]
  end
end

# Uses keyboard input from the user to make a decision
# Assigns the decision as the value of the decision_id variable
def process_inputs args
  decision = current_decision args # calls current_decision method

  if args.keyboard.key_down.left! && decision[:option_one] # if left key pressed and option one exists
    args.state.decision_id = decision[:option_one][:decision] # value of option one's decision hash key is set to decision_id
  end

  if args.keyboard.key_down.right! && decision[:option_two] # if right key pressed and option two exists
    args.state.decision_id = decision[:option_two][:decision] # value of option two's decision hash key is set to decision_id
  end

  if args.keyboard.key_down.down! && decision[:option_three] # if down key pressed and option three exists
    args.state.decision_id = decision[:option_three][:decision] # value of option three's decision hash key is set to decision_id
  end

  if args.keyboard.key_down.up! && decision[:option_four] # if up key pressed and option four exists
    args.state.decision_id = decision[:option_four][:decision] # value of option four's decision hash key is set to decision_id
  end
end

# Uses decision_id's value to keep track of current decision being made
def current_decision args
  args.state.game_definition[:decisions][args.state.decision_id] || {} # either has value or is empty
end

# Resets the game.
GTK.reset
