#          _____________________
#         |                     |
#         | Dilbert in MSWord©® |
#         |_____________________|
#
# Objectif : Récupérer sur le site www.dilbert.com 
# les strips et générer un document MSWord©® avec.
# 
# Ce code reprend largement des parties de code de
# René Nyffenegger :
# http://www.adp-gmbh.ch/perl/word.html
#
# ainsi que de Randal L. Schwartz :
# http://www.stonehenge.com/merlyn/WebTechniques/col15.html
#
# La doc de Philippe 'BooK' Bruhat concernant LWP
# a été d'un grand secours :
# http://articles.mongueurs.net/magazines/linuxmag57.html
#
#  
# Copyright 2004 by glb <glb@mongueurs.net>.
#
# This program is free software; you can  redistribute it 
# and/or modify it under the same terms as Perl itself.


use warnings;
use strict;
use integer;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft.Word';    # wd  constants
use Win32::OLE::Const 'Microsoft Office';  # mso constants
use URI::URL;
use LWP::UserAgent;
use Term::ReadKey;
use Getopt::Long;

my $ua = LWP::UserAgent->new;

my $TMP = $ENV{TMP} ? $ENV{TMP} : "./" ;
my ($proxy, $noproxy, $number, $user, $passwd) ;

BEGIN {

print <<"EOF";
 _________________________________________________
|                                                 |
|  Recuperation des derniers Dilbert sur le net ! |
|_________________________________________________|

EOF

}

GetOptions( "noproxy"  => \$noproxy,     # --noproxy
            "number=s" => \$number );    # --number=x

# Proxy ?

if ( not defined ($noproxy) ) {

  my $prox = "http://proxy.domaine.com:8080/";
  print "y'a-t-il des parametres proxy a renseigner ? [oui]";
  my $rep =<>;
  $rep = "oui" if $rep =~ m/^$/;
  if ($rep =~m/^(o|y).*/) {
    print "proxy ? [ $prox ] ";
    $proxy = <> ;
    $proxy = $prox if $proxy =~ m/^$/;
    print "user     ? ";
    $user = <>;
    print "password ? ";
    ReadMode 2;
    $passwd = <>;
    ReadMode 0;
    print "\n";
    chomp $proxy; chomp $user; chomp $passwd;
  } else {
    undef $proxy;
  }
}

if (not defined $number) {
  my $nbr_def = 7;
  my $nbr;
  print "combien d'images a recuperer ? [$nbr_def] " ;
  $nbr = <> ;
  $nbr = $nbr_def if ( $nbr !~ m/^\d+$/ );
  chomp  $nbr;
  $number = $nbr;
}

$number = ( $number < 32 ) ? $number : 32 ;

$ua->proxy('http', "$proxy" ) if defined $proxy;

# Les REGEXPs qui nous sont utiles
my $TOP     = "http://www.unitedmedia.com/comics/dilbert/archive/";
my $HTML_RE = 'VALUE="(/comics/dilbert/archive/dilbert-\d+.html)"';
my $GIF_RE  = '/comics/dilbert/archive/images/dilbert\d+\.(gif|jpg)';
my $NAME_RE = 'dilbert\d+\.(gif|jpg)';

my $cur_style    = 'a';
my $cur_bookmark = 'a';
my $word;

print "get $TOP\n";
my $top = get_as_string("$TOP", $proxy, $user, $passwd);

my @gif_urls = ();
if (not defined $top) {
  die  "Impossible de recuperer $TOP";
} else {
  my @old_urls = map url($_,$TOP)->abs, $top =~ m!$HTML_RE!og;

  die "Pas de donnees recuperees ?!?" if (@old_urls < 1) ;

  $word = CreateObject Win32::OLE 'Word.Application' or die $!;
  $word->{'Visible'} = 1;

  my $document = $word->Documents->Add;

  # selection is the insertion point.
  my $selection = $word->Selection;

  my $st_bold_10_arial   = create_style($document, "Arial", 10, 1, 0);
  my $st_bold_20_arial   = create_style($document, "Arial", 20, 1, 0);
  my $st_italic_10_arial = create_style($document, "Arial", 10, 0, 1);
  my $st_italic_20_arial = create_style($document, "Times new Roman", 20, 0, 1);
  my $st_normal_8_courier= create_style($document, "Courier", 8, 0, 0);

  set_style($document, $st_bold_20_arial);
  text     ($document, "Recent Dilberts");
  enter    ($document);
  set_style($document, $st_normal_8_courier);

  @old_urls = @old_urls[-$number..-1] if @old_urls > $number;

  for my $url (@old_urls) {
    print "get $url\n";

    my $page = get_as_string("$url", $proxy, $user, $passwd);

    my ($gif)      = $page =~ m!($GIF_RE)!o;
    my $url_img    = url($gif,$url)->abs;
    my ($name_img) = $url_img =~ m!($NAME_RE)!og;

    my $rc = get_file ("$url_img", "$TMP/$name_img", $proxy, $user, $passwd);
    text    ($document, "$url");
    enter   ($document);
    my $picture = insert_picture2($document, "$TMP/$name_img");
    go_right($document);
    enter   ($document);
    unlink  ("$TMP/$name_img");

}

  # insert something into the footer
  switch_view($document, wdSeekCurrentPageFooter);
  my $st_footer = create_style($document, "Verdana", 8, 0, 0);
  style_alignment($document, $st_footer, "wdAlignParagraphRight");
  set_style($document, $st_footer);
  text     ($document, localtime() . " - Recent Dilberts. ");

  # Inserting current page, total page
  text     ($document, " Page ");
  $selection->Fields->Add ($selection->{Range}, wdFieldPage    );
  text     ($document, " of ");
  $selection->Fields->Add ($selection->{Range}, wdFieldNumPages);

  # go back to body of document
  switch_view($document, wdSeekMainDocument);

  # save_doc_as($document, 'e:/dilbert.doc');
  # close_doc($document);
  # $word->Quit;

}

#--> Fonctions <---------------------------------------------------------------------------

sub get_as_string {

my ($url, $proxy, $user, $passwd) = @_ ;
my $content;
if ( defined $proxy ) {
  my $req = HTTP::Request->new(GET => "$url" );
  $req->proxy_authorization_basic("$user", "$passwd");
  $content = $ua->request($req)->as_string;
} else {
  #my $top = get $TOP or die "cannot get $TOP : $!\n";;
  $content = $ua->get($url)->as_string;
}

return $content ;

}

sub get_file {

my ($url, $file, $proxy, $user, $passwd) = @_ ;
my $rc ;

if ( defined $proxy ) {
  my $req_file = HTTP::Request->new( GET => "$url" );
  $req_file->proxy_authorization_basic( "$user", "$passwd" );
  $rc  = $ua->request( $req_file, "$file" );
} else {
  $rc  = $ua->get($url, ':content_file' => "$file");
}

return $rc ;
}


sub text {
  my $document = shift;
  my $text      = shift;

  $document->ActiveWindow->Selection -> TypeText($text);
}

# aka new line, newline or NL
sub enter {
  my $document = shift;

  $document->ActiveWindow->Selection -> TypeParagraph;
}

sub go_right {
  my $document = shift ;

  $document->ActiveWindow->Selection -> MoveRight ( wdCharacter, 1 );
}

sub set_style {
  my $document = shift;
  my $style_arg = shift;

  $document->ActiveWindow->Selection -> {Style} = $style_arg -> {name};
}

sub create_style {
  my $document  = shift;
  my $fontname  = shift;
  my $font_size = shift;
  my $bold      = shift;
  my $italic    = shift;

  my $style = $document->Styles->Add($cur_style);

  my $style_font = $style->{Font};

  $style_font -> {Name  } = $fontname;
  $style_font -> {Size  } = $font_size;
  $style_font -> {Bold  } = $bold;
  $style_font -> {Italic} = $italic;

  my %style;

  $style{name} = $cur_style++;
  return \%style;
}

# use switch_view to change to header, footer, main document and so on...
# possible constants for view are: wdSeekCurrentPageFooter 
#
#   o  wdSeekCurrentPageHeader 
#   o  wdSeekEndnotes 
#   o  wdSeekEvenPagesFooter 
#   o  wdSeekEvenPagesHeader 
#   o  wdSeekFirstPageFooter 
#   o  wdSeekFirstPageHeader 
#   o  wdSeekFootnotes 
#   o  wdSeekMainDocument 
#   o  wdSeekPrimaryFooter 
#   o  wdSeekPrimaryHeader 
#
sub switch_view {
  my $document = shift;
  my $view     = shift;
  $document -> ActiveWindow -> ActivePane -> View -> {SeekView} = $view;
}

sub insert_picture {
  my $document = shift;
  my $file     = shift;
  my $left     = shift;
  my $top      = shift;
  my $width    = shift;
  my $height   = shift;

  my $picture =
    $document-> Shapes -> AddPicture (
      $file,
      msoFalse, # link to file
      msoTrue,  # save with document
      $left, $top, $width, $height,
      $document->ActiveWindow->Selection->{Range}
    );

  return $picture;
}
sub insert_picture2 {
  my $document = shift;
  my $file     = shift;

  my $picture =
    $document-> InlineShapes -> AddPicture (
      $file,
      msoFalse, # link to file
      msoTrue,  # save with document
      $document->ActiveWindow->Selection->{Range}
    );

  return $picture;
}

sub bold {
  my $document = shift;
  my $bold     = shift;

  $document->ActiveWindow->Selection->{Font}->{Bold} = $bold ? msoTrue : msoFalse;
}

sub goto_bookmark {
  my $document = shift;
  my $bookmark = shift;

  $document->ActiveWindow->Selection -> GoTo(wdGoToBookmark, 0, 0, $bookmark->{Name});
}

sub insert_bookmark {
  my $document = shift;

  my $bookmark = $document -> Bookmarks -> Add ($cur_bookmark++, $document->ActiveWindow->Selection->Range);
  return $bookmark;
}

sub style_indents {
  my $document          = shift;
  my $style_arg         = shift;
  my $first_line_indent = shift;
  my $other_line_indent = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->ParagraphFormat->{LeftIndent     } =  $other_line_indent;
  $style->ParagraphFormat->{FirstLineIndent} = -$other_line_indent + $first_line_indent;
}

sub items {
  my $document = shift;
  my $title    = shift;
  my $style    = shift;
  my @array    = @_;

  enter($document);
  set_style($document, $style);

  bold($document, 1);
  text($document, $title);
  bold($document, 0);
  text($document, "\x09");

  foreach my $a (@array) {
    text($document, $a);
    text($document, "\x0b");
  }
}

sub insert_box {
  my $document = shift;
  my $left     = shift;
  my $top      = shift;
  my $width    = shift;
  my $height   = shift;

  my $shape = $document->Shapes->AddTextbox(msoTextOrientationHorizontal, $left, $top, $width, $height);
  $shape -> Select;
  my $selection = $word->Selection;
  $selection -> ShapeRange -> Line -> {DashStyle} = msoLineRoundDot;

  return $shape
}

sub close_doc {
  my $document = shift;
  $document -> Close;
}

sub save_doc_as {
  my $document = shift;
  my $filename = shift;

  $document->SaveAs($filename);
}

sub style_keep_with_next {
  my $document     = shift;
  my $style_arg    = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->{ParagraphFormat}->{KeepWithNext} = msoTrue;
}

sub style_keep_together {
  my $document     = shift;
  my $style_arg    = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->{ParagraphFormat}->{KeepTogether} = msoTrue;
}

sub style_border {
  my $document     = shift;
  my $style_arg    = shift;
  my $border       = shift;
  my $border_style = shift;
  my $border_width = shift;
  my $border_color = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->Borders($border) -> {LineStyle} = $border_style;
  $style->Borders($border) -> {LineWidth} = $border_width;
  $style->Borders($border) -> {Color    } = $border_color;
}

sub style_tab_at_position {
  my $document     = shift;
  my $style_arg    = shift;
  my $position     = shift;
  my $left_or_right= shift;

  my $style = $document->Styles($style_arg->{name});

  $style->ParagraphFormat->{TabStops}->Add($word->InchesToPoints($position), $left_or_right);
}

sub style_space_before {
  my $document     = shift;
  my $style_arg    = shift;
  my $space        = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->ParagraphFormat->{SpaceBefore} = $space;
}

sub style_space_after {
  my $document     = shift;
  my $style_arg    = shift;
  my $space        = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->ParagraphFormat->{SpaceAfter} = $space;
}

sub style_alignment {
  my $document     = shift;
  my $style_arg    = shift;
  my $alignment    = shift;

  my $style = $document->Styles($style_arg->{name});

  $style->ParagraphFormat->{Alignment} = $alignment;
}

sub goto_end_of_document {
  my $document  = shift;

  $document->ActiveWindow->Selection->{Range} -> EndKey(wdStory);

  #my $selection = $word->Selection;

  #$selection -> EndKey (wdStory);
}

sub insert_page_break {
  my $document  = shift;

  #my $selection = $word->Selection;

  #$selection -> InsertBreak(wdPageBreak);
  $document->ActiveWindow->Selection->{Range} -> InsertBreak(wdPageBreak);
}

sub landscape {
  my $document = shift;

  $document->PageSetup->{Orientation} = wdOrientLandscape;
}