<?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';

class GameView extends Wact_View_Partial {
    function setUp() {
        $this->onPreRenderDo($this, 'initializeLetterList');
        $this->onPreRenderDo($this, 'renderPuzzle');
    }
    
    /**
    * Initialize letter list
    */
    function initializeLetterList() {
        $guesses = $this->myScope->model->game->guesses;

        $availableLetters = array();
        for ($letter=65; $letter<=90; ++$letter) {
            $availableLetters[] = array(
              'letter' => chr($letter),
              'available' => (boolean) ((empty($guesses)) || (!is_integer(strpos($guesses, chr($letter)))))
            );
        }
        $this->setChildIterator('letterlist', $availableLetters);
    }

    /**
    * Render the puzzle
    */
    function renderPuzzle() {
        $word = $this->myScope->model->game->word;
        $guesses = $this->myScope->model->game->guesses;

        $puzzle = '';

        for ($i = 0; $i < strlen($word); $i++) {
            if (is_integer(strpos($guesses, $word{$i}))) {
                $puzzle .= $word{$i};
            } else {
                $puzzle .= '_';
            }
        }

        $this->myScope->model->game->puzzle = $puzzle;
    }
}

class Hangman extends Wact_Controller_Base {

    /**
    * setup the structure of our application.
    */
    function setup() {
        // the 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.
        // THe top level controller also defines a layout view with a placeholder named
        // 'main' that will be used by all the views of the game.
        $this->setView('templates/layout.tpl.html');
        $this->dispatchOn(new Wact_Request_None())->defaultTo('game');

        // The game controller manages the state of the game
        $this['game']->defineInput(new Wact_Request_PathInfo());
        $this['game']->dispatchOn(new Wact_Request_Segmented('command', 'PATH_INFO'))
            ->defaultTo('play');
        $this['game']->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['game']->defineInput(new Wact_Request_Url('level'))->bindToModel('game.level');
        $this['game']->defineInput(new Wact_Request_Url('word'))->bindToModel('game.word');
        $this['game']->defineInput(new Wact_Request_Url('guesses'))->bindToModel('game.guesses');
        $this['game']->defineInput(new Wact_Request_Url('misses'))->bindToModel('game.misses');

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

        // The giveup command ends the game and reveals the secret word
        $this['game']['giveup']->setPartialView('main', 'templates/lost.tpl.html');

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

        // Present the game view during game play
        $this['game']['play']->setPartialView('main', 'templates/game.tpl.html', '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', 'templates/lost.tpl.html');
        } else if ($responseModel->game->hasWon()) {
            $sender->setPartialView('main', 'templates/won.tpl.html');
        } else {
            // forward to the play controller
            return 'play';
        }
    }

}

Wact_Exception_Handler::installNew();

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

?>