/usr/local/CPAN/OpenThought/SoulFoodCafe.pm


package SoulFoodCafe;

use strict;
use lib "/home/eric/code/openthought2/lib";
use base 'CGI::Application';
use OpenThought();
use Apache::Session::File;

sub setup {
    my $self = shift;

    $self->run_modes([ qw(
            open_store
            show_storefront
            get_info
            get_menu
            add_item
            remove_item
            check_order
            checkout
            good_bye
    )]);

    $self->start_mode('open_store');
    $self->mode_param('run_mode');

}

sub cgiapp_init {
    my $self = shift;
    my $q    = $self->query;

    $self->param( 'OpenThought' => OpenThought->new() );

    my $session_id = $q->param('_session_id');
    my %session;

    if ( $session_id ) {
        $session_id =~ m/^(\w+)$/;
        $session_id = $1;
    }
    else {
        $session_id = undef;
    }

    tie %session, 'Apache::Session::File', $session_id, {
        Directory     => '/tmp/',
        LockDirectory => '/tmp/',
        Transaction   => 1
    };

    $self->param( 'session' => \%session );
    $session{SoulFoodCafe} || $self->_gen_menu_info();
}


sub teardown {
    my $self = shift;

}


sub open_store {
    my $self = shift;

    return $self->show_storefront;

}

sub get_menu {
    my $self = shift;
    my $OT   = $self->param('OpenThought');

    my $data;
    $data->{menu}       = $self->_get_menu_items();
    $data->{dinner}     = $self->_get_dinner();
    $data->{total_cost} = $self->_get_total_cost();

    $OT->param($data);
    return $OT->response();
}

sub add_item {
    my $self = shift;
    my $q    = $self->query;
    my $OT   = $self->param('OpenThought');

    my $menu_item = $q->param('menu');

    if ($menu_item eq "" ) {
        my $message   = "You have not selected an item!";
        my $javascript = "alert('$message')";

        $OT->javascript($javascript);
        return $OT->response();
    }
    else {
        my $added_item  = $self->_add_dinner_item( $menu_item );
        my $data;
        $data->{dinner}     = $added_item;
        $data->{total_cost} = $self->_get_total_cost;

        $OT->param($data);
        return $OT->response();
    }
}

sub remove_item {
    my $self = shift;
    my $q    = $self->query;
    my $OT   = $self->param('OpenThought');

    my $dinner_item = $q->param('dinner');

    if ($dinner_item eq "" ) {
        my $message   = "You have not selected an item!";
        my $javascript = "alert('$message')";

        $OT->javascript($javascript);
        return $OT->response();
    }
    else {
        my $removed_item  = $self->_remove_dinner_item( $dinner_item );

        my $data;

        $data->{dinner}     = $self->_get_dinner() if $removed_item;
        $data->{total_cost} = $self->_get_total_cost;

        $OT->param($data);
        $OT->focus("dinner");
        return $OT->response();
    }
}

sub show_storefront {
    my $self = shift;
    my $session = $self->param('session');

    my $template;

    # load_tmpl() uses HTML::Template to load a template document
    my $template_path = $self->_get_template_path;

    $template = $self->load_tmpl( "${template_path}/storefront.html" );
    $template->param({ session_id => $session->{_session_id} });

    return $template->output;
}


sub get_info {
    my $self    = shift;
    my $q       = $self->query;
    my $OT      = $self->param('OpenThought');

    my $menu      = $q->param('menu');
    my $meal_info = $self->_get_menu_info( $menu );

    #return $OT->parse_and_output({ auto_param => $meal_info, { data_mode => "auto" } });
    $OT->param( $meal_info );
    $OT->focus( "menu" );

    return $OT->response();
}

sub check_order {
    my $self = shift;
    my $q    = $self->query;
    my $OT   = $self->param('OpenThought');

    if ( $self->_get_dinner and @{ $self->_get_dinner } > 0 ) {
        my $session = $self->param('session');
        $OT->url( 'index.pl' => {
                                  run_mode => "checkout",
                                  _session_id => $session->{_session_id},
                                });
        return $OT->response();
    }
    else {
        my $message   = "You have not chosen your dinner!\\n" .
                        "Might I suggest the fried chicken?";
        my $javascript = "alert('$message')";

        $OT->javascript($javascript);
        return $OT->response();
    }

}

sub checkout {
    my $self = shift;
    my $session = $self->param('session');

    my $template_path = $self->_get_template_path;

    my $template = $self->load_tmpl( "${template_path}/checkout.html" );

    $template->param({ total_cost => $self->_get_total_cost,
                       session_id => $session->{_session_id} });

    return $template->output;
}

sub good_bye {
    my $self = shift;
    my $OT   = $self->param('OpenThought');

    my $message    = "Thanks for stopping by the Soul Food Cafe!";
    my $javascript = "alert('$message')";

    my $url = "http://openthought.net";

    $OT->javascript($javascript);
    $OT->url($url);
    return $OT->response();

}

sub _get_total_cost {
    my $self = shift;

    my $session = $self->param('session');

    return sprintf("%.2f", $session->{total_cost});
}

sub _add_dinner_item {
    my ( $self, $menu_id ) = @_;

    my $session = $self->param('session');

    my $add_item = [ $session->{menu}[$menu_id], $session->{unique_id}++ ];

    push @{ $session->{dinner} }, $add_item;
    $session->{total_cost} += $self->_get_menu_info( $menu_id )->{cost};

    $self->param('session' => $session );

    return $add_item;
}

sub _remove_dinner_item {
    my ( $self, $menu_item ) = @_;

    my $session = $self->param('session');

    my $remove_item;
    my $dinner         = $session->{dinner};
    $session->{dinner} = ();

    foreach my $item ( @{ $dinner } ) {
        if ( $item->[1] == $menu_item ) {
            $remove_item = $item;
            next;
        }

        push @{ $session->{dinner} }, $item;
    }

    return unless $remove_item;

    my $menu_id;
    for ( $menu_id = 0; $menu_id < @{ $session->{menu} }; $menu_id++ ) {
        last if $session->{menu}[$menu_id] eq $remove_item->[0];
    }

    $session->{total_cost} -= $self->_get_menu_info( $menu_id )->{cost};

    $self->param('session' => $session );

    return $remove_item;
}

sub _get_dinner {
    my $self = shift;

    my $session = $self->param('session');


#    if ( defined $session->{dinner} and
#         scalar @{ $session->{dinner} } > 0 ) {
        return $session->{dinner};
#    }
#    else {
#        return [ "-- Add Dinner Items --" ];
#    }
}

sub _get_menu_items {
    my $self = shift;

    my $session = $self->param('session');

    my $menu;

    for ( my $i=0; $i < @{ $session->{menu} }; $i++ ) {
        push @{ $menu }, [ $session->{menu}[$i], $i ];
    }

    return $menu;
}

sub _get_menu_info {
    my ( $self, $menu_item ) = @_;

    my $session = $self->param('session');

    return $session->{menu_info}[ $menu_item ];
}

sub _gen_menu_info {
    my $self    = shift;
    my $session = $self->param('session');

    # Generate menu information, but only if we haven't done it already
    unless ( exists $session->{SoulFoodCafe} and
             $session->{SoulFoodCafe} eq "open" ) {

        $session->{dinner} = ();
        $session->{total_cost} = 0;

        $session->{menu} = [
            "Fried Chicken",
            "Chicken Wings",
            "Chicken Nuggets",
            "Dry White Toast",
            "Dry Wheat Toast",
            "Coke",
            "Sprite",
        ];

        $session->{menu_info} = [
            {
                info => 'Best %*$# chicken in the state!',
                cost => '14.99',
            },
            {
                info => 'Hot wings',
                cost => '3.99',
            },
            {
                info => 'Tender chicken nuggets',
                cost => '1.69',
            },
            {
                info => 'Just plain white toast',
                cost => '1.30',
            },
            {
                info => 'Just plain wheat toast',
                cost => '1.30',
            },
            {
                info => 'A Coke',
                cost => '0.99',
            },
            {
                info => 'A Sprite',
                cost => '0.99',
            },
        ];

        $session->{unique_id} = 0;

        $session->{SoulFoodCafe} = "open";

        $self->param('session' => $session );
    }
}

sub _get_template_path {
    my $self = shift;

    return "$SoulFoodCafe::Path/templates";
}

1;