# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
#!/usr/bin/perl

# Copyright ©2004 W3C® (MIT, INRIA, Keio University),
# Written by Eric Prud'hommeaux to antagonize the World Wide Web Consortium

#Last update $Date: 2004/12/30 00:30:00 $ by $Author: eric $. $Revision: 1.4 $

use strict;

package W3C::Rnodes::cgibin::Contact;
use lib '/home/eric/sources/public/perl/modules/W3C/Rnodes/cgibin';
use ContactPresenter;
use W3C::Util::Exception;
use W3C::Util::W3CDebugCGI;
use DBI;
use Text::Iconv;
use URI::URL;

my $language = "en_us";
my $conf_path = "/etc/apache2/dbinfo.phi";

sub new {
    my ($proto, $read) = @_;
    my $class = ref $proto || $proto;
    my $self = {Read => $read, Converter => Text::Iconv->new('ISO-8859-1','utf-8')};
    bless ($self, $class);

    # Connect to database
    $self->{Connection} = $self->connect();

    # Pre-compile the queries

    # User info query...
    my @who = $read->param('who');
    my @email = $read->param('email');

    my $userQueryConstraint = "status=36";
    $self->{Who} = [undef];
    $self->{UserQuerySubstitutions} = []; # by default, no value substitution needed
    $self->{UserQueryMatchLike} = 0;
    if (@who) {
	if (@email) {
	    &throw(new W3C::Util::Exception(-message => "can't use who and email in the same query"));
	} else {
	    $self->{Who} = [@who];
	    $userQueryConstraint .= " && (family LIKE ? || email LIKE ? || given LIKE ? || peopleDetails.nick LIKE ?)";
	    $self->{UserQuerySubstitutions} = [1, 2, 3, 4]; # substitute who for above '?'s
	    $self->{UserQueryMatchLike} = 1;
	}
    } elsif (@email) {
	$self->{Who} = [@email];
	$userQueryConstraint .= " && (SUBSTRING(uris.uri,8)=? || SUBSTRING(alt.uri,8)=?)";
	$self->{UserQuerySubstitutions} = [1, 2]; # substitute who for email.
    }

    my @sort = $read->param('sort');
    my $userQueryOrderBy = @sort ? join(',', @sort) : "userDetails.family";

    $self->{UserQuery} = $self->{Connection}->prepare("
SELECT userDetails.id,userDetails.family,userDetails.given,
       SUBSTRING(uris.uri,8) AS email,peopleDetails.teamPage,
       peopleDetails.nick,peopleDetails.birthdate,
       SUBSTRING(alt.uri,8) AS altEmail,bio,image,title
  FROM userDetails
       INNER JOIN peopleDetails ON peopleDetails.id=userDetails.id
       INNER JOIN uris ON uris.id=userDetails.emailUrisId
       LEFT JOIN uris AS alt ON (peopleDetails.altEmailUrisId=alt.id)
 WHERE $userQueryConstraint
 ORDER BY $userQueryOrderBy");

    # Phone query...
    $self->{PhoneQuery} = $self->{Connection}->prepare("
SELECT phones.phone,phones.host,phones.site,phones.note,phones.id,phones.phonemeta
  FROM phones
 WHERE phones.idsId=?
 ORDER BY phones.id");

    # Domain query...
    $self->{DomainQuery} = $self->{Connection}->prepare("
SELECT domains.name
  FROM domainDetails
       INNER JOIN domains ON domains.id=domainDetails.id
 WHERE domainDetails.idsId=?");

    return $self;
}

sub execute {
    my ($self) = @_;
    my $queryList = defined $self->{Who}[0] ? $self->{Who} : undef;
    my @tArgs = ($self->{Read}->getSessionId(), $queryList);
    my $presenter = $ENV{'HTTP_ACCEPT'} =~ m/\bvcard\b/ ? new VCardPresenter(@tArgs) : 
	$ENV{'HTTP_ACCEPT'} =~ m/\brdf\b/ ? new RDFPresenter(@tArgs) : 
	$ENV{'HTTP_ACCEPT'} =~ m/\bsoap\b/ ? new SOAPPresenter(@tArgs) : 
	$ENV{'HTTP_ACCEPT'} =~ m/\bn3\b/ ? new N3Presenter(@tArgs) : 
	new XHTMLPresenter(@tArgs);
    $presenter->OKHeader;
    # print http header with "nice" headers
    $presenter->print_header(); # print HTML head and the beginning of the page

    foreach my $who (@{$self->{Who}}) {
	if ($self->{UserQueryMatchLike}) {
	    $who = "%$who%";
	}
	$presenter->showMatches($self->getContactData('W3C', $who, $self->{UserQuerySubstitutions}));
    }
    $presenter->print_foot();
    return $presenter;
}

sub fake {
    print "Status:200
Content-Type: text/plain

",join("\n", map {"$_: $ENV{$_}"} keys %ENV),"\n";
}

my ($query, $contact);
eval {
    local($SIG{"__DIE__"}) = \&DieHandler;
    $W3C::Util::W3CDebugCGI::DEBUG_SESSION = $ARGV[1]; # use a session id like 957296047.909868 or -2;
    $query = new W3C::Util::W3CDebugCGI($0, $ARGV[0] eq 'DEBUG', 
					{-dieNoOpen => 1, 
					 -logExt => '.log', 
					 -storeIn => '/tmp', 
					 -rerun => 'w3c_rerun'});

    $contact = new W3C::Rnodes::cgibin::Contact($query);
    my $presenter = $contact->execute();
    print $presenter->flush(200);
}; if ($@) {
    my $sessionId = $query ? $query->getSessionId : undef;
    if (my $ex = &catch('W3C::Http::HttpMessageException')) {
	if ($contact && $contact->{RDF_DB}) {
	    $contact->{RDF_DB}->disconnect;
	    delete $contact->{ACL_REPOSITORY};
	}
	my $message = $ex->getHttpMessage();
	$message->addHeader('Session-Id', $sessionId) if (defined $sessionId);
	print $message->toString;
    } elsif (my $ex = &catch('W3C::Rdf::CGIApp::AppException')) {
	print $ex->toString($sessionId);
    } elsif (my $ex = &catch('W3C::Util::Exception')) {
	print "Status: 500\n";
	print "Content-Type: text/html\n\n";
	my $title = $ex->getMessage;
	print "<html><head><title>$title</title></head><body>\n";
	print "<pre>".$ex->toString."</pre>\n";
	if ($sessionId) {
	    print "<p>Session-id: $sessionId</p>\n";
	}
	print "</body></html>\n";
    } else {
	print "Status: 500\n\n";
	print "died with $@";
	if ($sessionId) {
	    print "<p>Session-id: $sessionId</p>\n";
	}
    }
}

# SELECT userDetails.id,userDetails.family,userDetails.given,SUBSTRING(uris.uri,8) AS email,peopleDetails.teamPage,phones.phone,phones.host,phones.site,phones.note,phones.id,phones.phonemeta, peopleDetails.nick,peopleDetails.birthdate, SUBSTRING(alt.uri,8) AS altEmail FROM userDetails,peopleDetails,uris LEFT OUTER JOIN phones ON (userDetails.id=phones.idsId) left join uris as alt on (peopleDetails.altEmailUrisId=alt.id) WHERE status=36 AND peopleDetails.id=userDetails.id AND uris.id=userDetails.emailUrisId 

# If stuff isn't already in utf-8, iconv('ISO-8859-1','utf-8',$str)

# args for testing.
# also provides some documentation and examples of the parameters
sub fakeArgs {
    my $family = 'Haas';
    my $given = 'Hugo';
    my $teamPage = 'http://www.w3.org/Team/Hugo';
    my $org = 'W3C';
    my $title = 'Web Services Activity Lead';
    my $bday = '1975-04-19';
    my $nick = 'Larve';
    my $email = 'hugo@w3.org';
    my $altEmail = 'hugo@larve.net';
    my $phones = [['+1-617-395-0233', 'Office', 'ERCIM', 'Paris'], 
		  ['+33-6-73-84-87-26', 'Home', '', 'Paris']]; 
    my $domains = ['Architecture', 'Shmarchitecture'];
    my $bio = '<h1>geek</h1>';
    my $image = 'http://images.google.com/';
    my $url = 'http://www.w3.org/People/Hugo';

    return ([[$family, $given, $teamPage, $org, $title, $bday, $nick, 
	      $email, $altEmail, $phones, $domains, $bio, $image, $url]]);
}

sub connect {
    my ($self) = @_;

    my ($db_master, $db_mirror, $db_userid, $db_password, $db_name);

    open (DBCONF, $conf_path) || 
      &throw(new W3C::Util::FileOperationException(-filename => $conf_path, 
						   -operation => 'open'));
    foreach my $line (<DBCONF>) {
	if ($line =~ m/^\s*</) {
	    # <script language="php">
	} elsif ($line =~ m/^\s*$/) {
	    # empty line
	} elsif ($line =~ m/^\s*\#/) {
	    # comment
	} elsif ($line =~ m/^\s*\$(\w+)\s*=\s*(\"[^\"]*\")|(\'[^\']*\');/) {
	    eval $line;
	    if ($@) {&throw()}
	} else {
	    &throw(new W3C::Util::Exception(-message => 
					    "Couldn't parse \"$line\"."));
	}
    }
    close (DBCONF);

    my $connectString = 'DBI:mysql:'.$db_name; # .':'.$host.':'.$port;
    my $dbh = DBI->connect($connectString, $db_userid, $db_password, 
			   {'RaiseError' => 0, 'PrintError' => 0}) || 
	&throw(new W3C::Util::Exception(-message => 
			"can't connect to $connectString as $db_userid"));
    $dbh->{RaiseError} = 1;
    return $dbh;
}

sub getContactData {
    my ($self, $org, $who, $substitutions) = @_;
    my $ret = [];

    foreach my $substitution (@$substitutions) {
	$self->{UserQuery}->bind_param($substitution, $who);
    }
    $self->{UserQuery}->execute();
    while (my @row = $self->{UserQuery}->fetchrow_array()) {
	my ($userId, $family, $given, $email, $teamPage, 
	    $nick, $bday, $altEmail, $bio, $image, $title) = 
	      map {$self->{Converter}->convert($_)} @row;
	$teamPage = $self->relativeURL($teamPage, "http://www.w3.org/Team/");
	$image = $self->relativeURL($image, "http://www.w3.org/People/");

	my $phones = [];
	$self->{PhoneQuery}->bind_param(1, $userId);
	$self->{PhoneQuery}->execute();
	while (my @row = $self->{PhoneQuery}->fetchrow_array()) {
	    my ($phone, $host, $site, $note, $phoneId, $phonemeta) = @row;
	    push (@$phones, [$phoneId, $phone, $phonemeta, $host, $site, $note]);
	}

	my $domains = [];
	$self->{DomainQuery}->bind_param(1, $userId);
	$self->{DomainQuery}->execute();
	while (my @row = $self->{DomainQuery}->fetchrow_array()) {
	    my ($domain, $domainId) = @row;
	    push (@$domains, [$domain]);
	}

	push (@$ret, [$userId, $family, $given, $teamPage, $org, $title, $bday, 
		      $nick, $email, $altEmail, $phones, $domains, $bio, $image]);
    }
    return $ret;
}

sub relativeURL {
    my ($self, $url, $base) = @_;
    return URI::URL->new($url, $base)->abs();
}

