# frozen_string_literal: true module CodebreakerRuban class Console attr_accessor :state, :game, :user, :difficulty OPTION = { rules: 'rules', start: 'start', stats: 'stats', exit: 'exit' }.freeze HINT = 'hint' WIN = '++++' YES = %w[yes y].freeze EASY_STRING = 'easy' MEDIUM_STRING = 'medium' HELL_STRING = 'hell' def initialize set_state(:choice_option) end def run Message.greeting loop do send(state) break if state == :game_over end Message.goodbye end private def choice_option Message.choice_option(*OPTION.values) process_user_input do |input| case input when OPTION[:start] then set_state(:choice_name) when OPTION[:rules] then Message.rules when OPTION[:stats] then Statistic.show_stats else Message.wrong_command end end end def choice_name Message.enter_name process_user_input do |input| @user = User.new(input) @user.validate(input) @user.errors.empty? ? set_state(:choice_difficulty) : Message.display(@user.errors) end end def choice_difficulty Message.choice_difficulty(EASY_STRING, MEDIUM_STRING, HELL_STRING) process_user_input do |input| @difficulty = case input when EASY_STRING then Game::EASY when MEDIUM_STRING then Game::MEDIUM when HELL_STRING then Game::HELL end return Message.error_difficulty unless @difficulty set_state(:start_game) end end def start_game @game = Game.new(@difficulty, @user) set_state(:check_guess) end def check_guess Message.enter_code process_user_input do |input| if input == HINT Message.display(@game.hint_use) else @game.validate_guess_input(input) @game.errors.empty? ? check_win(input) : Message.display(@game.errors) end end end def check_win(input) if @game.check_attemps check_secret_and_guess = @game.check_user_input(input) Message.display(check_secret_and_guess) Message.win if game_result(check_secret_and_guess) else Message.lose Message.show_secret_code(@game.secret_code) set_state(:restart_game) end end def game_result(check_secret_and_guess) return unless check_secret_and_guess == WIN set_state(:save_result) end def save_result Message.save if YES.include? user_input Storage.save_in_store(@game.to_h) Message.result_save end set_state(:restart_game) end def restart_game Message.restart if YES.include? user_input set_state(:choice_option) else set_state(:game_over) end end def user_input gets.chomp.downcase end def game_over set_state(:game_over) end def process_user_input input = gets.chomp.downcase if input == OPTION[:exit] set_state(:game_over) else yield(input) end end def set_state(console_state) @state = console_state end end end