#!/usr/bin/perl -w

# Copyright 2007, 2008, 2009, 2010 Kevin Ryde

# This file is part of Gtk2-Ex-ErrorTextDialog.
#
# Gtk2-Ex-ErrorTextDialog 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 3, or (at your option) any
# later version.
#
# Gtk2-Ex-ErrorTextDialog 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 Gtk2-Ex-ErrorTextDialog.  If not, see <http://www.gnu.org/licenses/>.

use strict;
use warnings;

BEGIN {
  $ENV{'LANG'} = 'ja_JP.utf8';
  $ENV{'LC_ALL'} = 'ja_JP.utf8';
  delete $ENV{'LANGUAGE'};

  $ENV{'LANG'} = 'de_DE';
  $ENV{'LC_ALL'} = 'de_DE';
  $ENV{'LANGUAGE'} = 'de';

  require POSIX;
  print "setlocale to ",POSIX::setlocale(POSIX::LC_ALL(),""),"\n";
}

use Gtk2;
use Gtk2::Ex::ErrorTextDialog;
use Gtk2::Ex::ErrorTextDialog::Handler;

use FindBin;
use lib::abs $FindBin::Bin;
my $progname = $FindBin::Script;

print "$progname: MessageDialog has 'text': ",
  Gtk2::MessageDialog->find_property('text')?"yes":"no","\n";

print "$progname: STDERR prints wide ",
  (Gtk2::Ex::ErrorTextDialog::Handler::_fh_prints_wide('STDERR')
   ? "yes" : "no"), "\n";

{
  require Encode;
  require I18N::Langinfo;
  my $charset = I18N::Langinfo::langinfo (I18N::Langinfo::CODESET());
  { no warnings 'once';
    local $PerlIO::encoding::fallback = Encode::PERLQQ; # \x{1234} style
    (binmode (STDOUT, ":encoding($charset)") &&
     binmode (STDERR, ":encoding($charset)"))
      or die "Cannot set :encoding on stdout/stderr: $!\n";
  }
}

print "$progname: STDERR prints wide ",
  (Gtk2::Ex::ErrorTextDialog::Handler::_fh_prints_wide('STDERR')
   ? "yes" : "no"), "\n";

print "$progname: _locale_charset_or_ascii() is ",
  Gtk2::Ex::ErrorTextDialog::Handler::_locale_charset_or_ascii(), "\n";

{
  require Locale::Messages;
  print "$progname: dgettext of 'Error' in gtk20 is ",
    Locale::Messages::dgettext('gtk20','Error'),"\n";
}
{
  my @layers = PerlIO::get_layers('STDERR', output => 1, details => 1);
  require Data::Dumper;
  printf "$progname: last flags %#X\n", $layers[-1];
  print Data::Dumper->Dump([\@layers],['STDERR layers']);
}

Gtk2->disable_setlocale;  # leave LC_NUMERIC alone for version nums
Gtk2->init;
my $toplevel = Gtk2::Window->new ('toplevel');
$toplevel->signal_connect (destroy => sub {
                             print "$progname: quit\n";
                             Gtk2->main_quit;
                           });

my $vbox = Gtk2::VBox->new (0, 0);
$toplevel->add ($vbox);

# Gtk2::Ex::ErrorTextDialog->popup;

{
  my $button = Gtk2::Button->new_with_label ("add_message()");
  $button->signal_connect (clicked => sub {
                             print "$progname: add\n";
                             require Gtk2::Ex::ErrorTextDialog;
                             Gtk2::Ex::ErrorTextDialog->popup_add_message("\
hello
fdjsk
fsdjkl
\x{C1}

fsdjk fkjsd kfj sdk
ksdjfksdksdjf s
");
# \x{2028}\x{2029}\x{2014}\x{204A}
                           });
  $vbox->pack_start ($button, 0,0,0);
}

{
  my $button = Gtk2::Button->new_with_label ("die() error");
  $button->signal_connect (clicked => \&induce_an_error);
  $vbox->pack_start ($button, 0,0,0);

  sub induce_an_error {
    print "$progname: inducing an error\n";
    level1();
  }
  sub level1 {
    level2();
  }
  sub level2 {
    level3();
  }
  sub level3 {
    nosuchfunc("an ff - \x{FF}");
  }
}
{
  my $button = Gtk2::Button->new_with_label ("die() propagated error");
  $button->signal_connect (clicked => \&induce_a_propagated_error);
  $vbox->pack_start ($button, 0,0,0);

  sub induce_a_propagated_error {
    print "$progname: inducing a propagated error\n";
    eval { die 'an error' };
    die;
  }
}
{
  my $button = Gtk2::Button->new_with_label ("warn() message");
  $button->signal_connect
    (clicked => sub {
       print "$progname: inducing an warning\n";
       warn "some sort of perl warning, utf8 bullet \x{2022} end";
     });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("warn() continuation");
  $button->signal_connect (clicked => sub {
                             print "$progname: inducing an warning and continuation\n";
                             warn "first part of the warning";
                             warn "\t(an extra remark)";
                             warn "\ta second extra";
                           });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("g_warning()");
  $button->signal_connect
    (clicked => sub {
       print "$progname: calling g_warning\n";
       Glib->warning (undef, "warning about something, utf8 bullet \x{2022} end");
     });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("g_log()");
  $button->signal_connect (clicked => sub {
                             print "$progname: calling g_log\n";
                             Glib->log ('My-Domain', 'info', 'an informational log message');
                           });
  $vbox->pack_start ($button, 0,0,0);
  Glib::Log->set_handler ('My-Domain', ['warning','info'],
                          \&Gtk2::Ex::ErrorTextDialog::Handler::log_handler);
  if (Glib::Log->can('set_default_handler')) {
    Glib::Log->set_default_handler (\&Gtk2::Ex::ErrorTextDialog::Handler::log_handler);
  }
}
{
  my $n = 1;
  my $button = Gtk2::Button->new_with_label ("popup_add_message()");
  $button->signal_connect (clicked => sub {
                             Gtk2::Ex::ErrorTextDialog->popup_add_message ("hello world $n");
                             $n++;
                           });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("big add_message()");
  $button->signal_connect
    (clicked => sub {
       Gtk2::Ex::ErrorTextDialog->popup_add_message
           (join ("\n", 1 .. 50));
     });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("present() dialog");
  $button->signal_connect
    (clicked => sub {
       Gtk2::Ex::ErrorTextDialog->instance->present;
     });
  $vbox->pack_start ($button, 0,0,0);
}
{
  package MyGlobalDestructionBadObject;
  sub new {
    my ($class) = @_;
    my $self = bless { }, $class;
    $self->{'circular_reference'} = $self;
    return $self;
  }
  sub DESTROY {
    warn "$progname: warning within MyGlobalDestructionBadObject DESTROY";
  }
  package main;
  my $button = Gtk2::Button->new_with_label
    ("induce global destruction\nerror on exit");
  $button->signal_connect
    (clicked => sub {
       MyGlobalDestructionBadObject->new;
       print "$progname: will give a warning on exit\n";
     });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("load MyRunawayWarnAndError.pm");
  $button->signal_connect
    (clicked => sub {
       print "$progname: loading MyRunawayWarnAndError\n";
#        local $SIG{'__WARN__'} = sub {
#          print STDERR "(WARNING):\n";
#          warn @_;
#        };
#        local $SIG{'__DIE__'} = sub {
#          print STDERR "(DIE):\n";
#          die @_;
#        };
       require MyRunawayWarnAndError;
     });
  $vbox->pack_start ($button, 0,0,0);
}
{
  my $button = Gtk2::Button->new_with_label ("emit 'clear' signal");
  my $id;
  $button->signal_connect
    (clicked => sub {
       my $dialog = Gtk2::Ex::ErrorTextDialog->instance;
       $id ||= $dialog->signal_connect (clear => sub {
                                          print "$progname: clear signal\n";
                                        });
       $dialog->signal_emit('clear');
     });
  $vbox->pack_start ($button, 0,0,0);
}


$SIG{'__WARN__'} = sub {
  print STDERR "$progname __WARN__ handler:\n";
  print STDERR "  utf8 ",utf8::is_utf8($_[0])?"yes":"no","\n";
  goto \&Gtk2::Ex::ErrorTextDialog::Handler::exception_handler;
};

# $SIG{'__WARN__'} = sub {
#   require Devel::StackTrace;
#   my $trace = Devel::StackTrace->new;
#   my $str = $trace->as_string;
#   print "--------------\n$str\n---------------\n";
#   goto \&Gtk2::Ex::ErrorTextDialog::Handler::exception_handler;
# };
# $SIG{'__WARN__'} = \&Gtk2::Ex::ErrorTextDialog::Handler::exception_handler;

if (0) {
  my $stacktrace;
  require Devel::StackTrace;
  sub my_die_handler {
    $stacktrace = Devel::StackTrace->new (no_refs => 1);
    die;
  }
  $SIG{__DIE__} = \&my_die_handler;
  sub my_exception_handler_with_stacktrace {
    my ($msg) = @_;
    if (defined $stacktrace) {
      $msg = "$msg";
      $msg =~ /\n$/ or $msg .= "\n";
      $msg .= $stacktrace;
      Gtk2::Ex::ErrorTextDialog::Handler::exception_handler ($msg);
    }
  }
  Glib->install_exception_handler (\&my_exception_handler_with_stacktrace);
} elsif (0) {
  Glib->install_exception_handler
    (\&Gtk2::Ex::ErrorTextDialog::Handler::exception_handler);
} else {
  Glib->install_exception_handler
    (sub {
       print STDERR "Glib exception handler:\n";
       goto \&Gtk2::Ex::ErrorTextDialog::Handler::exception_handler;
     });
}


# Glib::Log->set_default_handler (sub {
#                                   my $dialog = Gtk2::Ex::ErrorTextDialog->popup;
#                                   $dialog->glog_handler(@_);
#                                 });
# sub glog_handler {
#   my ($self, $log_domain, $log_level, $message) = @_;
#   my $str = ((defined $log_domain ? "$log_domain-" : "** ")
#              . "\U$log_level\E: "
#              . (defined $message ? $message : "(no message)"));
#   $self->add_message ($str);
# }


$toplevel->show_all;
Gtk2->main;
exit 0;
