#!/usr/bin/perl
# 
# This file is part of Curses-Toolkit
# 
# This software is copyright (c) 2008 by Damien "dams" Krotkine.
# 
# This is free software; you can redistribute it and/or modify it under
# the same terms as the Perl 5 programming language system itself.
# 

use strict;
use warnings;

use lib qw(../lib);
main() unless caller;

use POE;

sub main {

	close STDERR;
	open STDERR, '>/dev/null';
	use POE::Component::Curses;

	use Curses::Toolkit::Widget::Window;
	use Curses::Toolkit::Widget::VBox;
	use Curses::Toolkit::Widget::HBox;
	use Curses::Toolkit::Widget::Button;
	use Curses::Toolkit::Widget::Border;
	use Curses::Toolkit::Widget::Entry;
	use Curses::Toolkit::Widget::HPaned;
	use Curses::Toolkit::Widget::Label;
	use Curses::Toolkit::Widget::Entry;

	my $root = POE::Component::Curses->spawn( args => { theme_name => 'Curses::Toolkit::Theme::Default' } );


	#1 ############# time label

	my ( $step1, $step2, $step3 );
	my ( $m, $s );
	$step1 = sub {
		my $move_label = 0;
		my $tick       = 0;

		my $time_window = Curses::Toolkit::Widget::Window->new();
		$time_window->set_name('time remaining'), $root->add_window($time_window);
		$time_window->set_theme_property( border_width => 0 );

		my $time_label = Curses::Toolkit::Widget::Label->new()->set_text('5:00')->set_name('label1');
		$time_window->add_widget($time_label);

		use Time::HiRes qw(time);
		POE::Session->create(
			inline_states => {
				_start => sub {
					$_[HEAP]->{min}             = 5;
					$_[HEAP]->{sec}             = 0;
					$_[HEAP]->{next_alarm_time} = int( time() ) + 1;
					$_[KERNEL]->alarm( tick => $_[HEAP]->{next_alarm_time} );
					$_[KERNEL]->delay_add( move_label => 1 / 10 );
				},
				tick => sub {
					if ($tick) {
						if ( $_[HEAP]->{sec} == 0 ) {
							if ( $_[HEAP]->{min} == 0 ) {
								print STDERR "timer elapsed\n";
							} else {
								$_[HEAP]->{min}--;
								$_[HEAP]->{sec} = 59;
							}
						} else {
							$_[HEAP]->{sec}--;
						}
						$time_label->set_text(
							$_[HEAP]->{min} . ':' . ( $_[HEAP]->{sec} < 10 ? '0' : '' ) . $_[HEAP]->{sec} );
						$root->needs_redraw();
					}
					$_[HEAP]->{next_alarm_time}++;
					$m = $_[HEAP]->{min};
					$s = $_[HEAP]->{sec};
					$_[KERNEL]->alarm( tick => $_[HEAP]->{next_alarm_time} );
				},
				move_label => sub {
					my ( $screen_h, $screen_w );
					if ($move_label) {
						$root->{curses_handler}->getmaxyx( $screen_h, $screen_w );
						my $c  = $time_label->get_coordinates();
						my $wc = $time_window->get_coordinates();
						my $nr = 0;
						int $c->x1() < $screen_w - 4 and $wc->set(
							x1 => $wc->x1() + 1,
							x2 => $wc->x2() + 1
							),
							$nr = 1;
						int $c->x1() > $screen_w - 4 and $wc->set(
							x1 => $wc->x1() - 1,
							x2 => $wc->x2() - 1
							),
							$nr = 1;
						int $c->y1() < 0 and $wc->set(
							y1 => $wc->y1() + 1,
							y2 => $wc->x2() + 1
							),
							$nr = 1;
						int $c->y1() > 0 and $wc->set(
							y1 => $wc->y1() - 1,
							y2 => $wc->x2() - 1
							),
							$nr = 1;
						$nr == 1 and $time_window->set_coordinates($wc);
						$nr == 1 and $root->needs_redraw();
					}
					$_[KERNEL]->delay_add( move_label => 1 / 6 );
				},
			},
		);

		my ( $screen_h, $screen_w );
		$root->{curses_handler}->getmaxyx( $screen_h, $screen_w );

		$time_window->set_coordinates(
			x1 => $screen_w / 2 - 2, y1 => $screen_h / 2,
			x2 => $screen_w / 2 + 2, y2 => $screen_h / 2 + 1,
		);

		$root->add_window(
			my $OK_window = Curses::Toolkit::Widget::Window->new()->set_theme_property( border_width => 0 )->add_widget(
				my $button1 =
					Curses::Toolkit::Widget::Button->new_with_label('Hit space when you are ready to start!')
					->add_event_listener(
					Curses::Toolkit::EventListener->new(
						accepted_event_class => 'Curses::Toolkit::Event::Key',
						conditional_code     => sub {
							my ($event) = @_;
							$event->{type} eq 'stroke' or return 0;
							$event->{params}{key} eq ' ' or return 0;
						},
						code => sub {
							my ( $event, $button ) = @_;
							$move_label = 1;
							$tick       = 1;
							$button->get_parent()->remove_widget();
							POE::Session->create(
								inline_states => {
									_start => sub {
										$poe_kernel->delay_add( start_step2 => 3 );
									},
									start_step2 => sub {
										$step2->();
									},
								}
							);
						},
					)
					)
				)->set_coordinates(
				x1 => ( $screen_w - 40 ) / 2,
				y1 => $screen_h / 2 + 1,
				x2 => ( $screen_w + 45 ) / 2,
				y2 => $screen_h / 2 + 2,
				)
		);
		$OK_window->set_theme_property( border_width => 0 );
		$button1->set_focus(1);
	};

	my $audience_window;
	my $audience_entry;
	my $label;

	my $flag;

	$step2 = sub {
		$root->add_window( my $window = Curses::Toolkit::Widget::Window->new()->set_title("This is a long title") );
		$window->set_theme_property( border_width => 0 );
		$window->set_coordinates(
			x1 => 3, y1 => '55%',

			#							  x2 => 50, y2 => 80,
			x2 => '100%', y2 => '100%',
		);
		$window->add_widget(
			$label = Curses::Toolkit::Widget::Label->new()->set_text(
				"Hello !                                                                           .\n                                                                           .\n                                                                           .\n                                                                           .\n                                                                           .\n\n\n"
			)
		);
		my $app = sub { $label->set_text( $label->get_text() . $_[0] ) };
		my $set = sub { $label->set_text( $_[0] ) };
		my $o   = 0;
		my $t   = sub { $o += ( $_[0] / 1 ); return $o; };
		$root->add_delay( $t->(5), sub { $set->("My name is Damien Krotkine\n") } );
		$root->add_delay( $t->(3), sub { $app->("I'm also known as 'dams'\n") } );
		$root->add_delay( $t->(3), sub { $set->("\n") } );
		$root->add_delay( $t->(3), sub { $set->("I am not the funny guy which is standing on the scene.\n") } );
		$root->add_delay( $t->(5), sub { $app->("The funny guy is called BooK, and I'm sure you all know him.") } );
		$root->add_delay(
			$t->(5),
			sub { $set->("I couldn't make it to the YAPC::EU this year\nso I asked Book to give this talk for me !") }
		);
		$root->add_delay( $t->(7), sub { $set->("") } );
		$root->add_delay( $t->(3), sub { $set->("OK. So what is this talk about ?\n") } );
		$root->add_delay( $t->(5), sub { $set->("this talk is about : ") } );
		$root->add_delay( $t->(5), sub { $app->("    Curses::Toolkit   !") } );
		$root->add_delay( $t->(5), sub { $set->("Curses::Toolkit is a\n") } );
		$root->add_delay( $t->(2), sub { $app->("modern ") } );
		$root->add_delay( $t->(1), sub { $app->("POE based ") } );
		$root->add_delay( $t->(1), sub { $app->("object oriented ") } );
		$root->add_delay( $t->(1), sub { $app->("widget oriented ") } );
		$root->add_delay( $t->(1), sub { $app->("GTK inspired ") } );
		$root->add_delay( $t->(1), sub { $app->("curses ") } );
		$root->add_delay( $t->(1), sub { $app->("toolkit !\n") } );
		$root->add_delay( $t->(5), sub { $set->("") } );
		$root->add_delay( $t->(5), sub { $set->("Book is kind enough to do things for me\n") } );
		$root->add_delay( $t->(2), sub { $app->("So I'll use that opportunity to ask him to help me\n") } );
		$root->add_delay( $t->(2), sub { $app->("While I'm demonstrating some features of Curses::Toolkit\n") } );
		$root->add_delay( $t->(5), sub { $set->("") } );
		$root->add_delay( $t->(2), sub { $set->("Book recently won the White Camel Award !\n") } );
		$root->add_delay( $t->(2), sub { $app->("So I think he deserves a lot of applause !\n") } );
		$root->add_delay( $t->(2), sub { $app->(" (Book, at this point, I suggest you bow)!\n") } );
		$root->add_delay(
			$t->(10),
			sub { $set->(" OK ! now back to business (Book, you can put your T-Shirt back on)\n") }
		);

		my $audience_label;
		$root->add_delay( $t->(5), sub { $set->("Let's start with a window\n"); } );
		$root->add_delay(
			$t->(2),
			sub {
				$root->add_window( $audience_window = Curses::Toolkit::Widget::Window->new() );
				$audience_window->set_coordinates(
					x1 => 3,  y1 => 3,
					x2 => 40, y2 => 10,
				);
				$audience_window->add_widget( $audience_label =
						Curses::Toolkit::Widget::Label->new()->set_text("Wow this is a cool window !") );

			}
		);
		$root->add_delay( $t->(2), sub { $app->("oh it's new and shiny !\n") } );
		$root->add_delay(
			$t->(2),
			sub {
				$set->(
					"The good thing about Curses::Toolkit is that\nyou don't have to mess with cordinates, the module handles it for you\n"
				);
			}
		);
		$root->add_delay( $t->(5), sub { $set->("For instance, I can move and resize the window\n") } );


		my $move_audience_window_sub;
		my $move_audience_window_sub2;
		my $loop1 = 20;
		my $loop2 = 12;
		$move_audience_window_sub = sub {
			my $wc = $audience_window->get_coordinates();
			$audience_window->set_coordinates(
				x1 => $wc->x1() + 1, x2 => $wc->x2(),
				y1 => $wc->y1(),     y2 => $wc->y2()
			);
			$loop1-- and $root->add_delay( 1 / 3, $move_audience_window_sub );
		};
		$move_audience_window_sub2 = sub {
			my $wc = $audience_window->get_coordinates();
			$audience_window->set_coordinates(
				x1 => $wc->x1() - 1, x2 => $wc->x2() + 1,
				y1 => $wc->y1(),     y2 => $wc->y2()
			);
			$loop2-- and $root->add_delay( 1 / 3, $move_audience_window_sub2 );
		};
		$root->add_delay( $t->(2),  $move_audience_window_sub );
		$root->add_delay( $t->(10), $move_audience_window_sub2 );
		$root->add_delay( $t->(5),  sub { $set->("I can also set a title\n") } );
		$root->add_delay(
			$t->(3),
			sub {
				$audience_window->set_theme_property( title_width => 50 );
				$audience_window->set_title("title");
			}
		);
		$root->add_delay( $t->(5),  sub { $set->("If the title is too big, it's animated\n") } );
		$root->add_delay( $t->(3),  sub { $audience_window->set_title("this is truely a very long title. fear !") } );
		$root->add_delay( $t->(5),  sub { $set->("") } );
		$root->add_delay( $t->(10), sub { $set->("All this is themable\n") } );
		$root->add_delay( $t->(2),  sub { $app->("I'll try to change the theme of the window\n") } );
		$root->add_delay( $t->(2),  sub { $app->("... hmmm let's seee....\n") } );
		$root->add_delay(
			$t->(4),
			sub {
				$audience_window->{theme} = Curses::Toolkit::Theme::Default::Color::Pink->new($audience_window);
				$audience_label->{theme}  = Curses::Toolkit::Theme::Default::Color::Pink->new($audience_label);
				$audience_window->set_theme_property( title_width => 50 );
				$root->needs_redraw();
			}
		);
		$root->add_delay( $t->(2), sub { $set->("There !") } );
		$root->add_delay( $t->(2), sub { $app->(" ... nice, uh ?") } );
		$root->add_delay( $t->(2), sub { $set->("") } );
		$root->add_delay( $t->(2), sub { $set->("Now the big show\n") } );
		$root->add_delay( $t->(2), sub { $app->("Mouse interactions !!\n") } );
		$root->add_delay( $t->(4), sub { $set->("Mr Book, can you please move the window\n") } );
		$root->add_delay( $t->(2), sub { $app->("by drag and dropping its title bar ?\n") } );
		$root->add_delay( $t->(2), sub { $app->("I'll give you 20 secs to play\n") } );

		my $loop3 = 20;
		my $sub3;
		$sub3 = sub {
			$audience_label->set_text("  ^ move me ^ ! $loop3 secs");
			$loop3-- and $root->add_delay( 1, $sub3 );
		};
		$root->add_delay( $t->(1), $sub3 );
		$root->add_delay( $t->(11), sub { $set->("10 secs left") } );
		$root->add_delay(
			$t->(10),
			sub {
				$set->("");
				$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
			}
		);
		$root->add_delay( $t->(2), sub { $set->("OK now, resize it please !") } );

		my $loop4 = 20;
		my $sub4;
		$sub4 = sub {
			$audience_label->set_text("  resize me ! $loop4 secs");
			$loop4-- and $root->add_delay( 1, $sub4 );
		};
		$root->add_delay( $t->(1), $sub4 );
		$root->add_delay( $t->(11), sub { $set->("10 secs left") } );
		$root->add_delay(
			$t->(10),
			sub {
				$set->("");
				$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
			}
		);
		$root->add_delay( $t->(2), sub { $set->("funny, isn't it ? ") } );
		$root->add_delay( $t->(4), sub { $set->("Let's try to see more widgets\n") } );
		$root->add_delay( $t->(2), sub { $app->("Let's have a look at boxes, Entry and Button") } );
		my $audience_button;
		$root->add_delay(
			$t->(2),
			sub {
				$audience_window->remove_widget();
				my $vbox = Curses::Toolkit::Widget::VBox->new();
				$audience_window->add_widget($vbox);
				$vbox->pack_end(
					$audience_entry =
						Curses::Toolkit::Widget::Entry->new_with_text('Enter some text')->set_name('entry1'),
					{ expand => 1 }
					)->pack_end(
					my $hbox = Curses::Toolkit::Widget::HBox->new()->pack_end(
						$audience_button = Curses::Toolkit::Widget::Button->new_with_label(' OK ')->set_name('button1'),
						{ expand => 0 }
					),
					{ expand => 0 }
					);
				$audience_button->add_event_listener(
					Curses::Toolkit::EventListener->new(
						accepted_event_class => 'Curses::Toolkit::Event::Key',
						conditional_code     => sub {
							my ($event) = @_;
							$event->{type} eq 'stroke' or return 0;
							$event->{params}{key} eq ' ' or return 0;
						},
						code => sub {
							my ( $event, $button ) = @_;
							$step3->();
						},
					)
				);
				$audience_window->{theme} = Curses::Toolkit::Theme::Default::Color::Yellow->new($audience_window);
				$audience_window->set_theme_property( title_width => 50 );
				$audience_entry->{theme}  = Curses::Toolkit::Theme::Default::Color::Yellow->new($audience_entry);
				$audience_button->{theme} = Curses::Toolkit::Theme::Default::Color::Yellow->new($audience_button);
				$hbox->{theme}            = Curses::Toolkit::Theme::Default::Color::Yellow->new($hbox);
				$vbox->{theme}            = Curses::Toolkit::Theme::Default::Color::Yellow->new($vbox);
				$audience_button->set_focus(1);
				$root->needs_redraw();
			}
		);
		$root->add_delay( $t->(1), sub { $set->("") } );
		$root->add_delay(
			$t->(1),
			sub { $set->("Please enter something in the entry and hit space on the button\n") }
		);
		$root->add_delay( $t->(2),  sub { $app->("You can use <tab> to navigate between widgets\n") } );
		$root->add_delay( $t->(2),  sub { $app->("Select the entry and hit Enter. Then : \n") } );
		$root->add_delay( $t->(1),  sub { $app->("You can use <Ctrl-A> and <Ctrl-E> to navigate\n") } );
		$root->add_delay( $t->(1),  sub { $app->("You can use the arrows, and <Ctrl-D> and maybe backspace\n") } );
		$root->add_delay( $t->(20), sub { $flag or $step3->(); } );
	};

	$step3 = sub {
		$flag = 1;
		$audience_window->remove_widget();
		my $app = sub { $label->set_text( $label->get_text() . $_[0] ) };
		my $set = sub { $label->set_text( $_[0] ) };
		my $o   = 0;
		my $t   = sub { $o += ( $_[0] / 1 ); return $o; };
		my $text = $audience_entry->get_text();
		$root->add_delay( $t->(1), sub { $set->(" You entered the text : '$text'") } );
		$root->add_delay( $t->(5), sub { $set->("OK ! Let's have a look at the Paned widget ! ") } );
		$root->add_delay(
			$t->(2),
			sub {
				my $hpane = Curses::Toolkit::Widget::HPaned->new();
				$hpane->set_name('hpane');
				$hpane->set_gutter_position(13);
				$audience_window->add_widget($hpane);
				$hpane->add1(
					my $l1 =
						Curses::Toolkit::Widget::Label->new()->set_text('This is a naive label. Very naive')
						->set_name('label1'),
				);
				$hpane->add2(
					my $l2 =
						Curses::Toolkit::Widget::Label->new()->set_text('An other nonetheless naive label.Honest !')
						->set_name('label2'),
				);
				$audience_window->{theme} = Curses::Toolkit::Theme::Default::Color::Pink->new($audience_window);
				$audience_window->set_theme_property( title_width => 50 );
				$hpane->{theme} = Curses::Toolkit::Theme::Default::Color::Pink->new($hpane);
				$l1->{theme}    = Curses::Toolkit::Theme::Default::Color::Pink->new($l1);
				$l2->{theme}    = Curses::Toolkit::Theme::Default::Color::Pink->new($l2);
				$root->needs_redraw();
			}
		);

		$root->add_delay( $t->(1), sub { $set->("Mister Book, can you please resize and move the window ?\n") } );
		$root->add_delay( $t->(2), sub { $app->("Oh and, can you drag and drop the Paned seperation ?\n") } );
		$root->add_delay( $t->(3), sub { $set->("") } );

		$root->add_delay(
			$t->(5),
			sub {
				$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
				$set->("That's all folks\n");
			}
		);
		$root->add_delay(
			$t->(2),
			sub {
				$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
				$app->("I hope you likes what you saw.\n");
			}
		);
		$root->add_delay(
			$t->(5),
			sub {
				$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
				$set->("More information : https://github.com/dams/curses-toolkit/\n");
			}
		);
		if ( $m > 0 || $s > 0 ) {
			$root->add_delay(
				$t->(5),
				sub {
					$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
					$app->("\nThere is still $m:$s to waste\n");
				}
			);
			$root->add_delay(
				$t->(2),
				sub {
					$audience_window->set_coordinates( x1 => 3, y1 => 3, x2 => 40, y2 => 10 );
					$app->("So Book will dance for you. Book ?\n");
				}
			);

		}
	};

	$step1->();
	POE::Kernel->run();
}