# BEGIN {unshift@INC,('../..');}

use ExtUtils::MakeMaker;
use Config;
use English;
use URI::URL;
use W3C::Util::Exception qw(&throw &catch &DieHandler);
use W3C::Util::AuthDBMUtils;
use strict;

my $REVISION = '$Id: Makefile.PL,v 1.14 2005/08/28 06:41:19 eric Exp $ ';

my @extras = ();

push(@extras,
     CAPI => 'TRUE')
    if ($PERL_VERSION >= 5.005 and $OSNAME eq 'MSWin32'
	and $Config{archname} =~ /-object\b/i);

push(@extras,
     ABSTRACT => 'scripts to implement the W3C Annotea server',
     AUTHOR   => 'Eric Prud\'hommeaux (eric@w3.org)')
    if ($ExtUtils::MakeMaker::Version >= 5.4301);

WriteMakefile(CONFIGURE => \ &configure);

my $UpdateApacheConf = '';

sub configure {
    local($SIG{"__DIE__"}) = \&DieHandler;
    my $ret;
    eval {
	$ret = &configure_protected;
    }; if ($@) {
	if (my $ex = &catch('W3C::Util::Exception')) {
	    die $ex->toString();
	} else {
	    die $@;
	}}
    return $ret;
}


sub configure_protected {
    my $exes = [ qw(bin/annoprox) ];
    my $scrp = [qw(cgibin/access cgibin/annotate cgibin/bookmark)];

    my $input = {ENABLE => {'annotate' => 0, 
			    'bookmark' => 0, 
			    'access' => 0}, 
		 PREREQS => {'W3C::Util::Exception' => 1.0, 
			     'W3C::Database::DBIInterface' => 1.0, 
			     'W3C::XML::XmlParser' => 1.0, 
			     'W3C::Rdf::XmlParser' => 1.0, 
			     'W3C::Http::Message' => 1.0, 
			     'URI' => 0 }};
    my $p = {};

    my $neededProperties = ['script.home.uri.ServerName', 
			    'script.home.uri.Port', 
			    'script.home.uri.Path', 
			    'script.url.path', 
			    'file.path', 
			    'auth.database.class', 
			    'auth.database.parms', 
			    ];

    # Look for flag file indicating we are making a distribution.
    if (-e '../MAKEDIST') {
	# Don't configure anything for distributions.
	goto end;
    }

  top:

    $input->{EXPLAINATION} = 1;

    # Find httpd.conf
    my $apacheConf = new W3C::Util::AuthDBMUtils();
  readConf:
    $apacheConf->readConf();

    # Find DBMAuth database format.
  AuthDBMFormat:

    my $authFileIsFlat = 0;
   if (defined (my $fmt = $apacheConf->findBestAuthFormat())) {
	if ($apacheConf->getAuthDir()) {
	    $p->{'file.path'} = $apacheConf->getAuthDir();
	}
	$p->{'auth.database.class'} = 'W3C::Annotations::DBMUserRecords';
	$p->{'auth.database.parms'} = "-type => '$fmt'";
    } else {
	if (&ExtUtils::MakeMaker::prompt(
"couldn't find a berkeley DB format that matched. Give up and use flat file?", 'y') =~ /^y/) {
	    # stick with flat password file
	    $p->{'auth.database.class'} = 'W3C::Annotations::FlatUserRecords';
	    $p->{'file.path'} = -d '/etc/apache2/' ? '/etc/apache2/' : 
		-d '/etc/apache/' ? '/etc/apache/' : 
		'./';
	    $authFileIsFlat = 1;
	} else {
	    goto AuthDBMFormat;
	}
    }

    my $annotUrl = URI::URL->new('http://localhost/annotations');
    my $annotUrlDir = '/';
    {
      promptAnnotUrl:
	my $annotUrlStr = &ExtUtils::MakeMaker::prompt('What will be the URL of your annotations server?', 'http://localhost/annotations');
	$annotUrl = URI::URL->new($annotUrlStr);
	my $serverName = $annotUrl->host;
	my $port = $annotUrl->port;
	my $path = $annotUrl->path;
	$annotUrlDir = URI::URL->new_abs('.', $annotUrl)->path();
	$p->{'script.home.uri.ServerName'} = $serverName;
	$p->{'script.home.uri.Port'} = $port;
	$p->{'script.home.uri.Path'} = $path;
	$p->{'script.url.path'} = $annotUrlDir;
    }

    my $bookmarkPath = URI::URL->new_abs('bookmark', $annotUrl)->path();
    my $bookmarkPathStr = &ExtUtils::MakeMaker::prompt('What will be the path to your bookmark script? (empty string disables bookmarks)', "$bookmarkPath");
    $bookmarkPath = URI::URL->new($bookmarkPathStr, $annotUrl)->path();

    my $accessPath = URI::URL->new_abs('access', $annotUrl)->path();
    my $authReqPath = URI::URL->new_abs('authRequired.html', $annotUrl)->path();
    if (&ExtUtils::MakeMaker::prompt("use the access script to create new user accounts?", 'y') =~ /^y/) {
	my $annotUrlPath = $annotUrl->path();
	system ('perl',  '-pi', '-e', 's|<a class=\"annolink\" href=\"[^\"]*\">|<a class=\"annolink\" href=\"$annotUrlPath\">|', 'htdocs/authRequired.html');

	my $accessPathStr = &ExtUtils::MakeMaker::prompt('What will be the path to your access script?', "$accessPath");
	$accessPath = URI::URL->new($accessPathStr, $annotUrl)->path();
	system ('perl',  '-pi', '-e', 's|<a class=\"accesslink\" href=\"[^\"]*\">|<a class=\"accesslink\" href=\"$accessPath\">|', 'htdocs/authRequired.html');

	my $authReqPathStr = &ExtUtils::MakeMaker::prompt('What document (path) will be served for 401 Auth Required responses?', "$authReqPath");
	$authReqPath = URI::URL->new($authReqPathStr, $annotUrl)->path();
	my $authReqFile = (File::Spec->splitdir($authReqPath))[-1];
    } else {
	$accessPath = undef;
	$authReqPath = undef;
    }

    if (&ExtUtils::MakeMaker::prompt("would you like to change these values?", 'y') !~ /^n/i) {
	goto top;
    }

    print "For your convenience, this install script can modify the demo property files
with this information. This will allow others to see the access information.\n";
    my $modify = &ExtUtils::MakeMaker::prompt("Would you like to modify the $ENV{PREFIX}/doc/W3C-Annotations-Kit/test/*.prop and authRequired.html with this data?", 'n');

    my $propFile = 'cgibin/annotate.prop';
    my $copyPropsFrom = '../W3C-Rdf-Kit-1/test/genericTripleStore.prop';

    my $copyPropFile;
    if (-e $propFile) {
	if (-e $copyPropsFrom && &mtime($copyPropsFrom) > &mtime($propFile) && 
	    &prompt("You already have a $propFile but $copyPropsFrom is newer.
Would you like to copy update $propFile", 'y') !~ /^n/i) {
	    $copyPropFile = 1;
	} else {
	    $copyPropFile = 0;
	}
    } else {
	$copyPropFile = 1;
    }

    if ($copyPropFile) {
	my $rdfPropFile = '';
	if (-e $copyPropsFrom) {
	    $rdfPropFile = $copyPropsFrom;
	} else {
	    $rdfPropFile = &ExtUtils::MakeMaker::prompt('Where is your rdf SqlDB properties file?', "$ENV{PREFIX}/doc/W3C-Rdf-Kit/test/genericTripleStore.prop");
	}
	if ($rdfPropFile) {
	    `cp $rdfPropFile $propFile`;
	} else {
	    `touch $propFile`;
	    print "annotate.prop may have no database access information.
You will need to update the file with:
queryHost: <hostname (or localhost)>
database: <database name>
user: <user name to access that database>
password: <user's password>";
	}
    }

    if ($modify =~ m/^\s*y/) {
	&updatePropsFile(['cgibin/annotate.prop'], $p, 
			 $neededProperties);

	# update the 401 document
	if ($accessPath) {
	    my $annotPath = $annotUrl->path;
	    $annotPath =~ s/\//\\\//g;
	    my $tAccessPath = $accessPath;
	    $tAccessPath =~ s/\//\\\//g;
	    `perl -pi.bak -e 's/a class=\"annolink\" href=\".*?\"/a class=\"annolink\" href=\"$annotPath\"/' htdocs/authRequired.html`;
	    `perl -pi.bak -e 's/a class=\"accesslink\" href=\".*?\"/a class=\"accesslink\" href=\"$tAccessPath\"/' htdocs/authRequired.html`;
	    print "authRequired.html updated\n";
	}
    }

    {
	#my $docInst = File::Spec->catpath("\$(PREFIX)", 'htdocs');
	#my $binInst = File::Spec->catpath("\$(PREFIX)", 'cgi-bin');
	my $docInst = '$(PREFIX)/htdocs';
	my $binInst = '$(PREFIX)/cgi-bin';
	my $verSuffix = '';

	if ($ENV{LOCAL}) {
	    my $t = `pwd`;
	    chomp $t;
	    my $makefile_pl = "$t/$0"; # File::Spec->catpath($t, $0);
	    my @path = File::Spec->splitdir($makefile_pl);
	    my $dir = join ('/', @path[0..@path-2]);
	    $docInst = "$dir/htdocs";
	    $binInst = "$dir/cgibin";
	}

	if ($ENV{PERL5LIB}) {
	    $verSuffix = '.cgi';
	}

	my ($host, $port) = ($annotUrl->host, $annotUrl->port);
	my $vhostMsg = " (You may ommit the
<VirtualHost $host:$port></VirtualHost> directive if you want your service
to run on all virtual hosts.";
	my $annotPath = $annotUrl->path;
	my $confFile = $apacheConf->getConfFileName();
	my $edit = 0; # &ExtUtils::MakeMaker::prompt("edit $confFile('n' to print needed edits instead)?", 'n') =~ /^y/;
	if ($edit) {
	    my $bakRev = '';
	    while (-e "$confFile.bak$bakRev") {
		$bakRev++;
	    }
	    if (system ('cp', $confFile, "$confFile.bak$bakRev") || 
		open (CONF, ">$confFile")) {
		# got an error copying the conf file
		$edit = 0;
		my $tmpdir = File::Spec->tmpdir() || 
		    die "can't find tmp directory: $!";
		my $tmpFile = (File::Spec->splitdir($confFile))[-1];
		my $tmpRev = '';
		while (-e "$tmpdir/$tmpFile$tmpRev") {
		    $tmpRev++;
		}
		open (CONF, ">$tmpdir/$tmpFile$tmpRev") || 
		    die "can't create tmp conf file \"$tmpdir/$tmpFile$tmpRev\": $!";
	    }
	}
	my $update = '';
	if (!$edit) {
	    $update .= "NameVirtualHost $host:$port
<VirtualHost $host:$port>

";


		$update .= "    Alias /annot-icons/ $docInst/icons/

";

	    if ($authReqPath) {
		$update .= "    ErrorDocument 401 $authReqPath
    Alias $authReqPath $docInst/authRequired.html

";
	    }

	    my $baseOptions = "        AllowOverride None
        Options ExecCGI
        Allow from all";
	    my $authFormat = $authFileIsFlat ? '' : 'DBM';
	    my $authOptions = "        AuthType Basic
        AuthName RDF
        Auth${authFormat}UserFile users
        Auth${authFormat}GroupFile groups
        <Limit PUT POST DELETE>
            Require group registered
        </Limit>";
	    $update .= "    ScriptAlias $annotPath	$binInst/annotate$verSuffix
    <Location \"$annotPath\">
$baseOptions
$authOptions
    </Location>

";
	    &maybeCreateCGI("$binInst/annotate$verSuffix", 'annotate') if ($verSuffix);

	    if ($accessPath) {
		$update .= "    ScriptAlias $accessPath	$binInst/access$verSuffix
    <Location \"$accessPath\">
$baseOptions
    </Location>

";
		&maybeCreateCGI("$binInst/access$verSuffix", 'access') if ($verSuffix);
	    }

	    if ($bookmarkPath) {
		$update .= "    ScriptAlias $bookmarkPath	$binInst/bookmark$verSuffix
    <Location \"$bookmarkPath\">
$baseOptions
$authOptions
    </Location>

";
		&maybeCreateCGI("$binInst/bookmark$verSuffix", 'bookmark') if ($verSuffix);
	    }

	    $update .= "</VirtualHost>
";
	}
	if ($ENV{LOCAL}) {
	    $UpdateApacheConf = '';
	    print "You need to add the following to $confFile:\n\n$update\n\n";
	} else {
	    $UpdateApacheConf = "\@echo -e \"".
		&shellEchoEscape("\nYou need to add the following to $confFile:\n\n").
		&shellEchoEscape($update).
		"\"";
	}
    }

    # Final arguments to emulate the contructor args to WriteMakefile
  end:
    return {  NAME         => 'W3C::Annotations::Kit',
              VERSION => 1.0,
              PREREQ_PM    => $input->{PREREQS},
              dist         => {COMPRESS => 'gzip', SUFFIX => '.gz'},
	      EXE_FILES    => $exes,
	      @extras};
}

sub shellEchoEscape {
    my ($text) = @_;
    $text =~ s/\\/\\\\/g;
    $text =~ s/\"/\\\"/g;
    $text =~ s/\n/\\n/g;
    return $text;
}

sub updatePropsFile {
    my ($fileList, $p, $lookFor) = @_;
    if (ref $lookFor eq 'ARRAY') {
	$lookFor = {map {$_ => undef} @$lookFor};
    }

    foreach my $file (@$fileList) {
	if (!open(PROP, $file)) {
	    die "could not read \"$file\": $!";
	}
	print "reading $file\n";
	my $lines = []; # lines from prop file

	# Get the existing lines.
	foreach my $line (<PROP>) {
	    foreach my $prop (keys %$lookFor) {
		if ($line =~ m/^\s*\Q$prop\E\s*\:\s*(.*)$/) {
		    my $value = $p->{$prop};
		    if ($1 ne $value) {
			push (@$lines, "# $line");
			$line = "$prop: $value\n";
		    }
		    delete $lookFor->{$prop};
		    last;
		}
	    }
	    push (@$lines, $line);
	}
	close (PROP);

	# Add needed lines at bottom.
	foreach my $prop (keys %$lookFor) {
	    my $value = $p->{$prop};
	    if ($value) {
		push (@$lines, "$prop: $value\n");
	    }
	}
	if (!open(PROP, '>', $file)) {
		die "could not write \"$file\": $!";
	    }
	foreach my $line (@$lines) {
	    print PROP $line;
	}
	close (PROP);
	print "$file updated\n";
    }
}

sub maybeCreateCGI {
    my ($cgi, $relay) = @_;
    if (! -e $cgi) {
	if (open (CGI, ">$cgi")) {
	    print CGI "#!/bin/sh
export PERL5LIB=$ENV{PERL5LIB}
perl ./$relay
";
	    close CGI;
	    `chmod +x $cgi`;
	} else {
	    warn "unable to create cgi script file \"$cgi\" to hold PERL5LIB variable.";
	}
    }
}

sub mtime {
    my ($filename) = @_;
    my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, 
	$atime, $mtime, $ctime, $blksize, $blocks) = stat($filename);
    return $mtime;
}

sub MY::postamble {
    return <<EOF;

install ::
	@\$(MOD_INSTALL) cgibin "\$(PREFIX)/cgi-bin"

install ::
	@\$(MOD_INSTALL) test "\$(PREFIX)/doc/W3C-Annotea-Kit/test"

install ::
	@\$(MOD_INSTALL) htdocs "\$(PREFIX)/doc/W3C-Annotea-Kit/htdocs"

install ::
	@\$(MOD_INSTALL) htdocs/icons "\$(PREFIX)/doc/W3C-Annotea-Kit/htdocs/icons"

install ::
	$UpdateApacheConf

EOF
}

