<?php

/*
Example Name: Hangman
Description: A simple hangman game designed to demonstrate WACT controllers and propagating state via HTTP without using sessions.<br \><small>(Ported from PRADO and refactored to eliminate viewstate and follow the MVC pattern.)</small>
*/

require_once '../../Wact/Loader.inc.php';
Wact_Loader::setupWact();

require_once 'model.inc.php';
require_once 'view.inc.php';

class PlayController extends Wact_Controller_Base {

    /**
    * setup the structure of our application.
    */
    function setup() {
        // The game controller manages the state of the game
        $this->defineInput(new Wact_Request_PathInfo());
        $this->dispatchOn(new Wact_Request_Segmented('command', 'PATH_INFO'))
            ->defaultTo('play');

        $this->onFocusDo($this, 'ensureGameState');

        // The game state would normally be saved in a session.
        // We represent the state as HTTP GET request parameters in order to demonstrate that
        // we can.
        $this->defineInput(new Wact_Request_Url('level'))->bindToModel('game.level');
        $this->defineInput(new Wact_Request_Url('word'))->bindToModel('game.word');
        $this->defineInput(new Wact_Request_Url('guesses'))->bindToModel('game.guesses');
        $this->defineInput(new Wact_Request_Url('misses'))->bindToModel('game.misses');

        // The guess command processes the user's guess of a letter
        $this['guess']->onExecuteDo($this, 'guess');
        $this['guess']->defineInput(new Wact_Request_Url('letter'));

        // The giveup command ends the game and reveals the secret word
        $this['giveup']->setPartialView('main', new LosingView());

        // Display a view that allows the user to select the level of play
        $this['start']->setPartialView('main', new StartingView());
        $this['start']->onExecuteDo($this, 'startGame');

        // Present the game view during game play
        $this['play']->setPartialView('main', new GameView());
    }

    /**
    * Start a new game
    */
    function startGame($sender, $request, $responseModel) {
        $responseModel->game->pickRandomWord();
    }

    /**
    * Establish the state of the game
    */
    function ensureGameState($sender, $request, $responseModel) {

        // establish the model which our application will use
        $responseModel->game = new HangmanGame();

        // If any of our required state is missing, start a new game
        if (!isset($request->level) || 
            !isset($request->word) ||
            !isset($request->guesses) ||
            !isset($request->misses)
            ) {
                // forward to the start controller
                return 'start';
        }
    }

    /**
    * Guess a letter in the hangman game.
    */
    function guess($sender, $request, $responseModel) {

        // translate the input parameter to a request on the model
        $responseModel->game->guess($request->letter);
        
        if ($responseModel->game->hasLost()) {
            $sender->setPartialView('main', new LosingView());
        } else if ($responseModel->game->hasWon()) {
            $sender->setPartialView('main', new WinningView());
        } else {
            // forward to the play controller
            return 'play';
        }
    }
}

class HangmanApplication extends Wact_Controller_Base {

    /**
    * setup the structure of our application.
    */
    function setup() {
        // This top level controller ('/') serves as the "new game" command.
        // It must be located above any controllers that define input because
        // the new game command requires no input.

        // We are a wrapping controller; always transfer control to our child
        $this->dispatchOn(new Wact_Request_None())->defaultTo('game');
        $this['game'] = $this->config->createPlayController();

        // Define a layout view with a placeholder 'main' used by all views of the game.
        $this->setView(new LayoutView());
    }

}

$config = new Wact_Config_Registry();
$config->HangmanApplication->start();

?>