#!/usr/bin/perl
# drakcowsay

# Copyright (C) 2004 Olivier Blin(blino@mandrake.org)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

use MDK::Common;
use lib qw(/usr/lib/libDrakX);
use Fcntl qw(O_WRONLY O_NONBLOCK);
require ugtk2;
ugtk2->import(qw(:wrappers :create));

my %cowsay_options;
my ($cowsay_message, $cowsay_buffer);
my $mature_cows; #- do not show obscene cows by default

my $cowsay_code = cat_("/usr/bin/cowsay");
$cowsay_code =~ s/^&.*$//mg; #- remove calls to cowsay subs
$cowsay_code =~ s/^\s*print.*$//mg; #- remove calls to print, but keep sprintf
#- rework list_cowfiles so that it returns an array of cows instead of printing them
$cowsay_code =~ s/\@dirfiles = \(\);(.*?)exit\(0\);/$1return \@dirfiles;/s;
#- word-wrapping function
$cowsay_code =~ s/(\@message = \(\$opts{'n'}.*?\);)/sub wordwrap_message { $1 }/s;
#- get boolean options
push @{$cowsay_options{bool}}, $1 while $cowsay_code =~ m!^\$([^:\s]+?) = \$opts{'\S'};$!mg;
#- get string options
push @{$cowsay_options{text}{$2}}, $1 while $cowsay_code =~ m!^\$([^:\s]+?) = substr\(\$opts{'\S'}, 0, (\d)\)+;$!mg;
eval $cowsay_code;

my $program_name = $0;
$program_name =~ s!.*/!!;

@message = $ARGV[0] eq '-' ? <STDIN> : @ARGV ? join(' ', @ARGV) : "welcome to $program_name";
chomp(@message);

sub gtkset_width_chars { $_[0]->set_width_chars($_[1]); $_[0] }

sub send_to_fifo {
    my $fifo = $ENV{HOME} . "/.drakcowsay-fifo";
    -p $fifo && sysopen(my $F, $fifo, O_WRONLY | O_NONBLOCK) or return;
    print $F $_ foreach @balloon_lines, $the_cow;
    close $F;
}

sub refresh_cowsay_buffer {
    $eyes = $cowsay_options{eyes} || $opts{e};
    $tongue = $cowsay_options{tongue} || $opts{T};
    @balloon_lines = ();
    @message = split("\n", $cowsay_message->get_text($cowsay_message->get_bounds, 0));
    eval {
        wordwrap_message();
        construct_balloon();
        construct_face();
        get_cow();
    };
    if ($@) {
	$cowsay_buffer->set_text("Error:\n$@");
	return;
    }

    $cowsay_buffer->set_text(join("", @balloon_lines) . $the_cow);
    $cowsay_buffer->apply_tag($cowsay_buffer->create_tag(undef, 'font', 'Fixed 14'), $cowsay_buffer->get_bounds);
}

sub parental_advisory_enabled_list_cowfiles {
    sort(difference2([ list_cowfiles() ], [ if_(!$mature_cows, qw(sodomized telebears)) ]));
}

sub update_cows_tv {
    my ($list_tv) = @_;
    my $list = Gtk2::ListStore->new("Glib::String");
    $list->append_set([ 0 => $_ ]) foreach parental_advisory_enabled_list_cowfiles();
    $list_tv->set_model($list);
}

my $cows_list_tv = Gtk2::TreeView->new;
$cows_list_tv->set_headers_visible(0);
$cows_list_tv->get_selection->set_mode('browse');
$cows_list_tv->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0));
$cows_list_tv->get_selection->signal_connect(changed => sub {
						 my ($model, $iter) = $_[0]->get_selected or return;
						 $opts{f} = $model->get($iter, STRING_COLUMN);
						 refresh_cowsay_buffer();
});

update_cows_tv($cows_list_tv);

my $w = ugtk2->new($program_name);
gtkadd($w->{window},
       gtkpack_(Gtk2::HBox->new(0,0),
                1, gtkpack_(Gtk2::VBox->new(0,0),
                            0, gtkset_border_width(gtkset_size_request(create_scrolled_window(my $input_text_view = Gtk2::TextView->new), 400, 100), 5),
                            1, gtkset_border_width(gtkset_size_request(create_scrolled_window(my $output_text_view = Gtk2::TextView->new), 400, 300), 5)),
                1, gtkpack(gtkset_border_width($w->create_box_with_title("Cowsaylection"), 5),
			   gtkset_size_request(create_scrolled_window($cows_list_tv), 150, 0)),
		0, gtkpack(gtkset_border_width(Gtk2::VBox->new(0,0), 5),
                           gtkpack__($w->create_box_with_title("Cowptions"),
                                     map {
                                         my $option = $_;
                                         gtkpack__(Gtk2::HBox->new(0,0),
                                                   gtksignal_connect(gtkset_active(Gtk2::CheckButton->new($option), $$option),
                                                                     clicked => sub {
                                                                         $$option = $_[0]->get_active;
                                                                         refresh_cowsay_buffer();
                                                                     }))
                                     } @{$cowsay_options{bool}}),
                           gtkpack__($w->create_box_with_title("Cowstumisation"),
                                   gtksignal_connect(gtkset_active(Gtk2::CheckButton->new("Word wrap"), !$opts{n}),
                                                     clicked => sub {
                                                         $opts{n} = !$_[0]->get_active;
                                                         refresh_cowsay_buffer();
                                                     }),
                                     map {
                                         my $width = $_;
                                         map {
                                             my $option = $_;
                                             gtkpack_(Gtk2::HBox->new(0,0),
                                                      1, $option,
                                                      0, gtksignal_connect(gtkset_width_chars(Gtk2::Entry->new_with_max_length($width), $width),
                                                                           activate => sub {
                                                                               $cowsay_options{$option} = $_[0]->get_text;
                                                                               refresh_cowsay_buffer();
                                                                           }))
                                         } @{$cowsay_options{text}{$width}}
                                     } keys %{$cowsay_options{text}}),
			   gtkpack__($w->create_box_with_title("Parental advisory"),
				     Gtk2::HBox->new(0,0),
				     gtksignal_connect(gtkset_active(Gtk2::CheckButton->new("I am over 18"), $mature_cows),
						       clicked => sub {
							   $mature_cows = $_[0]->get_active;
							   update_cows_tv($cows_list_tv);
						       })),
                           gtkpack(gtkset_layout(Gtk2::VButtonBox->new, 'end'),
                                   gtksignal_connect(Gtk2::Button->new_with_label("Send to IRC"), clicked => \&send_to_fifo),
                                   gtksignal_connect(Gtk2::Button->new("Quit"), clicked => sub { Gtk2->main_quit },
                                                    )))));

$input_text_view->set_wrap_mode('word');
$cowsay_message = $input_text_view->get_buffer;
$cowsay_message->set_text(join("\n", @message));
gtksignal_connect($cowsay_message, changed => \&refresh_cowsay_buffer);

$cowsay_buffer = $output_text_view->get_buffer;
$output_text_view->set_editable(0);

refresh_cowsay_buffer();

$w->main;
