#!/Perl
# 
use strict;
use Cwd;
###use Win32::OLE qw(EVENTS);
use Win32::OLE qw(in valof with OVERLOAD EVENTS);
use Data::Dump qw(dump);
##use Data::Dump ();
use Data::Dumper;
use UNIVERSAL qw( isa can VERSION );
###require UNIVERSAL ;

my ($URL, $se1, $va1, $se2, $va2);
# from : http://www.perl.com/pub/a/2005/04/21/win32ole.html
$URL = "http://samie.sf.net/simpleform.html";
$se1 = 'name';
$va1 = 'samie';

##$URL = 'http://login.live.com/login.srf?id=2&vv=400&lc=1033';
##$se1 = 'login';
##$va1 = 'geoffair@hotmail.com';
##$URL = 'http://geoffmclane.com/page4.htm';
##$se1 = 'year';
##$va1 = '2007';
$URL = 'http://geoffmclane.com/prods/prod1.htm';
$se1 = 'username';
$va1 = 'mem1';

# max5 site - try PHP ...
$URL = 'http://macpcfirstaid.com/download/login04.php';
$se1 = 'username';
$va1 = 'user2';
$se2 = 'password';
$va2 = 'pass2';

my $IEObject;
my @arr1 = ();
my @arr2 = ();

# LOG FILE STUFF
my ($LOG);
my $write_log = 0;
my $outfile = "$0.txt";
if ( open( $LOG, ">$outfile" ) ) {
    $write_log = 1;
} else {
    $write_log = 0;
    prt( "WARNING: Unable to open $outfile LOG ...\n" );
}

prt("Opening Internet Explorer instance ...\n");
my $IE  = Win32::OLE->new("InternetExplorer.Application")
    || mydie( "Could not start Internet Explorer.Application\n" );

prt("Setting up a callback of events ...\n");
Win32::OLE->WithEvents($IE,\&Event,"DWebBrowserEvents2");

$IE->{visible} = 1;

prt("Navigating to the URL [$URL] ...\n");
$IE->Navigate($URL);

prt("Entering the message loop, until document complete ...\n");
Win32::OLE->MessageLoop();

prt( "Out of message loop ...\n" );

Enumerate_Forms();
prt( "Object type = ". Win32::OLE->QueryObjectType($IEObject) ."\n" ); 

prt("Setting edit box ...\n" );
###SetEditBox("name","samie");
##SetEditBox( $se1, $va1 );
SetEditBox( $se1, $va1 );
SetEditBox( $se2, $va2 );

prt("All done ...\n");
##close_log();

exit 0;

######################################################################
### services
############

sub Event {
	my ($txt, $num, $IEO, $value, $yes);
    my ($Obj,$Event,@Args) = @_;
	for my $arg (@Args) {
		#if (UNIVERSAL::isa($value, 'Win32::OLE')) {
		#	$value = sprintf "[%s %s]", Win32::OLE->QueryObjectType($arg);
		#	prt( " arg: $value\n" );
		##$yes = UNIVERSAL::isa $arg, 'Win32::OLE'; 
		$yes = isa $arg, "Win32::OLE";
		if ($yes) {
			$value = sprintf "[%s %s]", Win32::OLE->QueryObjectType($arg);
			prt( " arg: $value\n" );
		} else {
			### prt( " Not ...\n" );
		}
	}
    prt( "Here is the Event: $Event " );
    if ($Event eq "DocumentComplete") {
		# void DocumentComplete( IDispatch *pDisp,
		#     VARIANT *URL );
        $IEObject = shift @Args;
        prt( "Here is my reference: $IEObject\n" );
		###prt( Dumper($IEObject) ); # does not show anything?
        prt( "URL: " .  $IEObject->Document->URL . "\n" );
		prt( "Quitting message loop ..." );
		Win32::OLE->QuitMessageLoop();
    } elsif ($Event eq 'StatusTextChange') {
		$txt = shift @Args;
		if (length($txt) > 0) {
			prt("Text is [$txt]");
		} else {
			prt("Text is [BLANK]");
		}
    } elsif ($Event eq 'CommandStateChange') {
		$num = shift @Args;
		if ($num == -1) {
			prt( "CSC_UPDATECOMMANDS change... " );
		} elsif ($num == 1) {
			prt( "CSC_NAVIGATEFORWARD change... " );
		} elsif ($num == 2) {
			prt( "CSC_NAVIGATEBACK change... " );
		} else {
			prt( "Change $num ... " );
		}
		if (@Args) {
			my $bl = shift @Args;
			prt("Bool [$bl] ");
		} else {
			prt("No bool! ");
		}
    } elsif ($Event eq 'ProgressChange') {
		my $n1 = shift @Args;
		my $n2 = shift @Args;
		if ($n1 == -1) {
			prt( "Progess COMPLETED ($n1 of $n2) done ..." );
		} else {
			prt( "Progess is $n1 of $n2 done ..." );
		}
    } elsif ($Event eq 'TitleChange') {
		$txt = shift @Args;
		if (length($txt) > 0) {
			prt("Title is [$txt]");
		} else {
			prt("Title is [BLANK]");
		}
    } elsif ($Event eq 'FileDownload') {
		$num = shift @Args;
		if ($num) {
			prt( "Is active document ..." );
		} else {
			prt( "Is NOT active document ..." );
		}
    } elsif (($Event eq 'DownloadBegin')||($Event eq 'DownloadComplete')) {
		prt("VOID");
    } elsif ($Event eq 'PropertyChange') {
		$txt = shift @Args;
		prt("$txt");
    } elsif ($Event eq 'BeforeNavigate2') {
		# void BeforeNavigate2( IDispatch *pDisp,
		#     VARIANT *&url,
		#     VARIANT *&Flags,
		#     VARIANT *&TargetFrameName,
		#     VARIANT *&PostData,
		#     VARIANT *&Headers,
		#     VARIANT_BOOL *&Cancel );
        $IEO = shift @Args;
		prt("First ref: $IEO ");
		#if (@Args) {
		#	my @arr = shift @Args;
		#	###$txt = shift @Args;
		#	prt( "URL = ". scalar @arr. " ". pop( @arr ));
		#}
    } elsif ($Event eq 'OnVisible') {
		$num = shift @Args;
		prt( " = $num");
    } elsif ($Event eq 'NavigateComplete2') {
        $IEO = shift @Args;
		prt("Second ref: $IEO ");
    }
	prt( "\n" );
}

sub SetEditBox {
    my ($name, $value) = @_;
    my $IEDocument = $IEObject->{Document}; # Returns the active Document automation object, if any.
	if ($IEDocument) {
		my $forms = $IEDocument->forms;
		prt("Got automation object ... extracting forms ...\n");
		if ($forms) {
			my $max = $forms->length;
			prt("Got forms object ... length $max ...\n");
			for (my $i = 0; $i < $max; $i++) {
				my $form = $forms->item($i);
				if (defined($form->elements($name))) {
					prt("Setting $name to $value ...\n");
				   $form->elements($name)->{value} = $value;
				   return;
				}
				#return;
			}
		} else {
			prt("No forms found in Automation object ...\n");
		}
	} else {
		prt("Automation object NOT found ...\n");
	}
}

sub Enumerate_Forms {
	my $cnt = 0;
	my $Count = Win32::OLE->EnumAllObjects(sub {
	    my $Object = shift;
	    my $Class = Win32::OLE->QueryObjectType($Object);
		$cnt++;
		# printf "$cnt # Object=%s Class=%s\n", $Object, $Class;
	    prt( "$cnt # Object = ". valof $Object . " Class = " . valof $Class . "\n" );
	    ##prt( "$cnt # Object = ". $Object . " Class = " . $Class . "\n" );
		#foreach my $k (in $Object) {
		#	prt("Key = $k, Value = ". $Object->{$k} . "\n");
		#}
	});
}

sub Enumerate_Forms_2 {
    my $IEDocument = $IEObject->{Document}; # Returns the active Document automation object, if any.
	if ($IEDocument) {
		my $forms = $IEDocument->forms;
		prt("Got automation object ... extracting forms ...\n");
		if ($forms) {
			my $max = $forms->length;
			prt("Got $max forms objects ... \n");
			for (my $i = 0; $i < $max; $i++) {
				my $form = $forms->item($i);
				my $ele = $form->elements;
				my $type1 = ref($form);
				my $type2 = ref($ele);
				prt("Got form $form ($type1),\nelement $ele ($type2)...\n");
				## *** ALL OF THESE JAM UP *** ??????????
				## prt( Data::Dumper->Dump([$doc], [qw(doc)]) );
				##prt("Dump:[" . Data::Dumper->Dump([$form], [qw(form)]) . "]\n");
				##prt("Dump:[" . Data::Dumper->Dump([$ele], [qw(element)]) . "]\n");
				##prt( dump($form) );
				###prt("Dump:" . Data::Dump::dump($ele) . "\n");
				push(@arr1, $form);
				push(@arr2, $ele);
			}
		} else {
			prt("No forms found in Automation object ...\n");
		}
	} else {
		prt("Automation object NOT found ...\n");
	}
}


################################
### output and log file
sub wlog {
	my $ml = shift;
	print $LOG $ml;
}

sub prt {
	my $m = shift;
	if ($write_log) {
		wlog($m);
	}
	print $m;
}

sub mydie {
	my $msg = shift;
	if ($write_log) {
		wlog($msg);
	}
	die $msg;
}

sub close_log {
	if ($write_log) {
		prt( "Closing LOG file, and passing to 'system($outfile)'\nMay need to CLOSE notepad to continue ...\n" );
		close( $LOG );
		system( $outfile );
	}
}

###################################################################################
### excerpts from Microsoft documentation -
# from : http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/reference/ifaces/dwebbrowserevents2/dwebbrowserevents2.asp
# DWebBrowserEvents2::DocumentComplete Event
# Fires when a document has been completely loaded and initialized.
# Syntax
# void DocumentComplete(  IDispatch *pDisp, VARIANT *URL );
# Parameters
# pDisp - [in] Pointer to the IDispatch interface of the window or frame in which the document has 
#         loaded. This IDispatch interface can be queried for the IWebBrowser2 interface. 
# URL - [in] Pointer to a VARIANT structure of type VT_BSTR that specifies the URL, 
#         Universal Naming Convention (UNC) file name, or pointer to an item identifier list 
#         (PIDL) of the loaded document. 

# autoie02.pl
