# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
# Copyright ©2004 W3C® (MIT, INRIA, Keio University),

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

use strict;

my $MID = "http://www.w3.org/mid/";
my $REFMARK = ";reference";
my %VCALTypes = ('Fax' => 'FAX,WORK', 
		 'Home' => 'VOICE,HOME', 
		 'Home Office' => 'VOICE,WORK', 
		 'Main' => 'VOICE,PREF', 
		 'Mobile' => 'CELL', 
		 'Office' => 'VOICE,WORK', 
		 'Other' => 'VOICE', 
		 'Skype' => 'VOICE,INTERNET');

package PresenterException;
@PresenterException::ISA = qw(W3C::Util::Exception);
@PresenterException::REVISION = '$Id: ContactPresenter.pm,v 1.4 2004/12/30 00:30:00 eric Exp $ ';

package Presenter;
use CGI qw/:standard/;
sub new {
    my ($proto, $sessionId, $queryList) = @_;
    my $class = ref($proto) || $proto;
    my $self = {SESSION_ID => $sessionId, BUFFER => '', QueryList => $queryList};
    bless ($self, $class);
    return $self;
}

# Utility functions used by subclasses

sub print {
    my ($self, @printables) = @_;
    $self->{BUFFER} .= join('', @printables);
}

sub OKHeader {
    my ($self) = @_;
    $self->print(header( -Cache_Control => 'max-age=3600', 
			 Content_Type => $self->getContentType,
			 Content_Language => 'en',
			 Status => '200 OK'));
}

sub flush {$_[0]->{BUFFER}}

sub xmlEncode {
    my ($d, $a) = @_;
    $a =~ s/\&/\&amp;/g;
    $a =~ s/\"/\&quot;/g;
    $a =~ s/\</\&lt;/g;
    $a =~ s/\>/\&gt;/g;
    return $a;
}

sub splitAddrEncode {
    my ($self, $fullAddr) = @_;
    my ($name, $addr) = (undef, $self->xmlEncode($fullAddr));
    if ($fullAddr =~ m/^\s*\"?\s*([^\"\<]+)\s*\"?\s*\<([^\>]+)\>\s*/) {
	($name, $addr) = ($1, $self->xmlEncode($2));
	$name =~ s/\s*$//;
	$name = $self->xmlEncode($name);
    }
    return ($name, $addr);
}

# some default presentation functions:

sub getContentType {'text/plain'}

# N3 and RDF don't have a rendering for these at present as no clients would
# know how to deal with an RDF form.
sub print_simple_form {}
sub print_adv_form {}

use Date::Manip;
BEGIN{&Date_Init("TZ=GMT")};
sub dateISO {
    my ($self, $str) = @_;
    if (my $d = &ParseDateString($str)) {
	return &UnixDate(&Date_ConvTZ($d, 'GMT'), "%Y-%m-%dT%H:%M:%SZ")
    } else {
	return undef;
    }
}

package VCardPresenter; # per RFC2426
@VCardPresenter::ISA = qw(Presenter);

sub getContentType {'text/x-vcard; charset=utf-8'} # Per RFC2425

sub print_header {
    my ($self) = @_;
}

sub print_foot {
    my ($self) = @_;
}

# Omitted Evolution fields:
#X-EVOLUTION-FILE-AS:$family\, $given
#ADR;TYPE=HOME:;;35\, rue Nationale;Paris;;75013;France
#ADR;TYPE=WORK:;;35\, rue Nationale;Paris;;75013;France
#LABEL;TYPE=HOME:35\, rue Nationale\nParis\n75013\nFrance
#LABEL;TYPE=WORK:35\, rue Nationale\nParis\n75013\nFrance
#X-EVOLUTION-LAST-USE:2004-12-22
#X-EVOLUTION-USE-SCORE:132.142181
#X-MOZILLA-HTML:FALSE
#UID:pas-id-41CC6D0200000323
#TITLE:
#ROLE:
#X-EVOLUTION-MANAGER:
#X-EVOLUTION-ASSISTANT:
#X-EVOLUTION-SPOUSE:
#NOTE:
#X-EVOLUTION-BLOG-URL:
#CALURI:
#FBURL:
#X-EVOLUTION-VIDEO-URL:
#EMAIL;TYPE=WORK; -->X-EVOLUTION-UI-SLOT=1<-- :$email
#TEL;TYPE=$type; -->X-EVOLUTION-UI-SLOT=$uislot<-- :$number\n

sub showMatches {
    my ($self, $results) = @_;
    foreach my $result (@$results) {
	my ($userId, $family, $given, $teamPage, $org, $title, $bday, $nick, $email, $altEmail, $phones, $domains, $bio, $image, $peoplePage) = @$result;
	my $guessHost = '';

	for (my $i = 0; $i < @$phones; $i++) {
	    my $phone = $phones->[$i];
	    my ($phoneId, $number, $phonemeta, $host, $site, $note) = @$phone;
	    if ($host ne 'Other' && $host ne '') {
		$guessHost = $host;
		last;
	    }
	}

	my $domainList = join(',', map {$_->[0]} @$domains);

	$self->print("BEGIN:VCARD
VERSION:3.0
FN:$given $family
N:$family;$given;;;
URL:$teamPage
ORG:$org/$guessHost;$domainList
TITLE:$title
CATEGORIES:$guessHost
BDAY:$bday
PHOTO;VALUE=uri:$image
NICKNAME:$nick
EMAIL;TYPE=WORK:$email
EMAIL;TYPE=OTHER:$altEmail\n");

	for (my $i = 0; $i < @$phones; $i++) {
	    my $phone = $phones->[$i];
	    my ($phoneId, $number, $phonemeta, $host, $site, $note) = @$phone;
	    my $type = $VCALTypes{$phonemeta} || '???';
	    $self->print("TEL;TYPE=$type:$number\n");
	}

	$self->print("END:VCARD\n\n");
    }
}

sub print_Exception {
    my ($self, $exception) = @_;
    my $message = $self->xmlEncode($exception->getMessage);
    $self->print("X-Exception:\"$message\".
");
}

sub print_warning {
    my ($self, $message) = @_;
    $message = $self->xmlEncode($message);
    $self->print("X-Warning:\"$message\".
");
}

sub print_resultCount {
    my ($self, $count) = @_;
}

package N3Presenter;
@N3Presenter::ISA = qw(Presenter);

sub getContentType {'application/vnd.w3c.n3'}

sub print_header {
    my ($self) = @_;
    $self->print("\@prefix email: <http://www.w3.org/2000/10/swap/pim/email#>.
\@prefix log: <http://www.w3.org/2000/10/swap/log#>.
\@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
\@prefix VCard: <http://www.w3.org/2001/vcard-rdf/3.0#>.
\@prefix session: <http://dev.w3.org/cvsweb/perl/modules/W3C/Util/W3CDebugCGI.pm>.
<> session:id \"$self->{SESSION_ID}\".

");
}

sub print_foot {
    my ($self) = @_;
}

sub showMatches {
    my ($self, $results) = @_;
    foreach my $result (@$results) {
	my ($userId, $family, $given, $teamPage, $org, $title, $bday, $nick, $email, $altEmail, $phones, $domains, $bio, $image, $peoplePage) = @$result;
	my $guessHost = '';
	my $prefix = undef;

	for (my $i = 0; $i < @$phones; $i++) {
	    my $phone = $phones->[$i];
	    my ($phoneId, $number, $phonemeta, $host, $site, $note) = @$phone;
	    if ($host ne 'Other' && $host ne '') {
		$guessHost = $host;
		last;
	    }
	}

	my $domainList = join(',', map {$_->[0]} @$domains);

	$self->print("[
    VCard:FN \"$given $family\" ;
    VCard:N [
        VCard:Family \"$family\" ;
        VCard:Given \"$given\" ");
	if ($prefix) {
	    $self->print(";\n        VCard:Prefix \"$prefix\"");
	}
	$self->print("] ;
    VCard:URL <$teamPage> ;
    VCard:ORG \"$org/$guessHost;$domainList\" ;
    VCard:TITLE \"$title\" ;
    VCard:CATEGORIES \"$guessHost\" ;
    VCard:BDAY \"$bday\" ;
    VCard:PHOTO <$image> ;
    VCard:NICKNAME \"$nick\" ;
    VCard:EMAIL [
        VCard:TYPE VCard:WORK ;
        rdf:value <mailto:$email>
    ] ;
    VCard:EMAIL [
        VCard:TYPE VCard:WORK ;
        rdf:value <mailto:$altEmail>
    ]");

	for (my $i = 0; $i < @$phones; $i++) {
	    my $phone = $phones->[$i];
	    my ($phoneId, $number, $phonemeta, $host, $site, $note) = @$phone;
	    my $type = $VCALTypes{$phonemeta} || '???';
	    $self->print(" ;
    VCard:TEL [
        rdf:value <tel:$number> ;
        VCard:TYPE \"$type\"
    ]");
	}

	$self->print("
] .\n");
    }
}

sub print_Exception {
    my ($self, $exception) = @_;
    my $message = $self->xmlEncode($exception->getMessage);
    $self->print("<> search:exception \"$message\".

");
}

sub print_warning {
    my ($self, $message) = @_;
    $message = $self->xmlEncode($message);
    $self->print("<> search:exception \"$message\".

");
}

sub print_resultCount {
    my ($self, $count) = @_;
    $self->print("    <rdf:Description rdf:about=\"\">
        <search:resultCount>$count</search:resultCount>
    </rdf:Description>

");
}

package RDFPresenter;
@RDFPresenter::ISA = qw(Presenter);

sub getContentType {'application/rdf+xml'}

sub print_header {
    my ($self) = @_;
    $self->print("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>
");
    $self->print_RDFElement;
    $self->print("    <rdf:Description rdf:about=\"\" session:id=\"$self->{SESSION_ID}\"/>\n\n");
}

sub print_RDFElement {
    my ($self) = @_;
    $self->print("<rdf:RDF xmlns:email=\"http://www.w3.org/2000/10/swap/pim/email#\"
    xmlns:log=\"http://www.w3.org/2000/10/swap/log#\"
    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
    xmlns:search=\"http://www.w3.org/Team/2001/09/search/search.pl#\"
    xmlns:session=\"http://dev.w3.org/cvsweb/perl/modules/W3C/Util/W3CDebugCGI.pm\">

");
}

sub print_foot {
    my ($self) = @_;
    $self->print('</rdf:RDF>
');
}

sub showMatches {
    my ($self, $count, $begin, $end, $perPage, $scriptInvocation, $keyword, $results) = @_;
    foreach my $result (@$results) {
	my $tauth = $result->[5];
	my ($ordinal, $mid, $subject, $score, $bytes, $author, $date, $access, $trimlist, $rmailNo, $uri, $sample, $replto, $refs) = map {$self->xmlEncode($_)} @$result;
	my ($authorName, $authorAddr) = $self->splitAddrEncode($result->[5]);
	my $authorNameStr = $authorName ? "            <email:phrase>$authorName</email:phrase>;\n": '';
	my $isoDate = $self->dateISO($date);
	my $isoDateStr = $isoDate ? "        <email:date_iso>$isoDate</email:date_iso>\n" : '';
	$self->print("    <rdf:Description rdf:about=\"mid:$mid\">
        <email:date>$date</email:date>
$isoDateStr        <email:subject>$subject</email:subject>
        <email:from rdf:parseType=\"Resource\">
$authorNameStr            <email:mbox rdf:resource=\"mailto:$authorAddr\"/>
        </email:from>
        <email:to rdf:parseType=\"Resource\">
            <email:mbox rdf:resource=\"mailto:$trimlist\@w3.org\"/>
        </email:to>
        <email:senders>$authorAddr</email:senders>
        <email:recipients>$trimlist\@w3.org</email:recipients>\n");
	if ($replto) {
	    $self->print("        <email:replyTo rdf:resource=\"${MID}${replto}${REFMARK}\"/>\n");
	}
	if (@$refs) {
	    $self->print("        <email:referencesL rdf:parseType=\"Collection\">\n");
	    for (my $i = 0; $i < @$refs; $i++) {
		$self->print("            <rdf:Description rdf:about=\"${MID}$refs->[$i]${REFMARK}\"/>\n");
	    }
	    $self->print("        </email:referencesL>\n");
	}
	for (my $i = 0; $i < @$refs; $i++) {
	    $self->print("        <email:references rdf:resource=\"${MID}$refs->[$i]${REFMARK}\"/>\n");
	}
	$self->print("    </rdf:Description>\n\n");
    }
}

sub print_Exception {
    my ($self, $exception) = @_;
    my $message = $self->xmlEncode($exception->getMessage);
    $self->print("    <rdf:Description rdf:about=\"\">
        <search:exception>$message</search:exception>
    </rdf:Description>

");
}

sub print_warning {
    my ($self, $message) = @_;
    $message = $self->xmlEncode($message);
    $self->print("    <rdf:Description rdf:about=\"\">
        <search:warning>$message</search:warning>
    </rdf:Description>

");
}

sub print_resultCount {
    my ($self, $count) = @_;
    $self->print("    <rdf:Description rdf:about=\"\">
        <search:resultCount>$count</search:resultCount>
    </rdf:Description>

");
}

package SOAPPresenter;
@SOAPPresenter::ISA = qw(RDFPresenter);

sub getContentType {'application/soap+xml'}

sub print_header {
    my ($self) = @_;
    $self->print("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>
<env:Envelope xmlns:env=\"http://www.w3.org/2003/05/soap-envelope\"
   xmlns:email=\"http://www.w3.org/2000/10/swap/pim/email#\"
   xmlns:search=\"http://www.w3.org/Team/2001/09/search/search.pl#\"
   xmlns:session=\"http://dev.w3.org/cvsweb/perl/modules/W3C/Util/W3CDebugCGI.pm\">
 <env:Header>
  <session:id>$self->{SESSION_ID}</session:id>
 </env:Header>
 <env:Body>
");
    $self->print_RDFElement;
}

sub print_foot {
    my ($self) = @_;
    $self->SUPER::print_foot;
    $self->print('
 </env:Body>
</env:Envelope>
');
}

sub print_Exception {
    my ($self, $exception) = @_;
    my $message = $self->xmlEncode($exception->getMessage);
    $self->print("
        <search:exception>$message</search:exception>

");
}

sub print_warning {
    my ($self, $message) = @_;
    $message = $self->xmlEncode($message);
    $self->print("
        <search:warning>$message</search:warning>

");
}

sub print_resultCount {
    my ($self, $count) = @_;
    $self->print("
        <search:resultCount>$count</search:resultCount>

");
}

package XHTMLPresenter;
@XHTMLPresenter::ISA = qw(Presenter);
use POSIX qw(ceil);
use CGI qw/:standard/;
use W3C::Util::Exception;

sub getContentType {'text/html'}

sub _readTemplate {
    my ($self, $template) = @_;
    open (H, $template) || 
      &throw(new W3C::Util::FileOperationException(-filename => $template, 
						   -operation => 'open'));
    local $/ = undef;
    foreach my $line (<H>) {
	$self->print($line);
    }
    close (H);
}

sub print_header {
    my ($self) = @_;
    my $title = $self->{QueryList} ? 'Contact Info for '.join(',', @{$self->{QueryList}}) : 'The Global Team at Work: The W3C Team Directory';
    $self->print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
  <head>
    <meta name=\"generator\" content=\"$0\" />
    <title>$title</title>
    <link rel=\"stylesheet\" href=\"/StyleSheets/team.css\" type=\"text/css\" />
    <meta http-equiv='Content-Type' content='text/html; charset=us-ascii' />
  </head>
  <body>
    <div class=\"navbar\">
      <a href=\"../\"><img src=\"../Icons/WWW/w3c_home\"alt=\"W3C\" border=\"0\" /></a>
      <a href=\"../Team/\"><img src=\"../Icons/WWW/team\" alt=\"Team\" border=\"0\" /></a>
    </div>
    <h1 align=\"center\">$title</h1>\n");
    if (!$self->{QueryList}) {
	$self->print("
    <p>See also:</p>
    <form action=\"/Team/Phonelist\">
      <ul>
        <li><a href=\"../Project/Teleconference\">Teleconference info</a>, e.g. <a href=\"../1998/12/bridge/\">The W3C bridge</a>;</li>
        <li><a href=\"./#Sites\">Host Site Info</a> for pics, home phone number, home</li>
        <li><a href=\"#SysteamContactInfo\">Systeam Contact Info</a> addresses, etc.</li>
        <li><a href=\"#ec-info\">Emergency Communications Info</a></li>
        <li><input type=\"checkbox\" name=\"birthdate\" value=\"1\" /> Display Birthdate if available</li>
        <li><select name=\"host\">
            <option value=\"all\">All Hosts</option>
            <option value=\"ERCIM\">ERCIM</option>
            <option value=\"MIT\">MIT</option>
            <option value=\"KEIO\">Keio</option>
            </select>
            <input type=\"submit\" /></li>
       </ul>
    </form>
");
    }
    $self->{Table} = [];
    $self->{Index} = [];
}

sub print_foot
{
    my ($self) = @_;
    if (@{$self->{Index}} > 1) {
	my $count = @{$self->{Index}};
	$self->print("    <h2 align=\"center\">$count Team Members</h2>
    <hr />
    <center>\n");
	map {$self->print("$_ ")} @{$self->{Index}};
	$self->print("    </center>
    <hr />\n");
    }
    if (@{$self->{Table}}) {
	$self->print("    <table border=\"1\">
      <tr>
        <th><b><a href=\"/Team/Phonelist?order=userDetails.family\">Family</a></b>, <a href=\"/Team/Phonelist?order=userDetails.given\">Given</a><br />
Email</th>
        <th>Phone</th>
        <th>Note</th>
      </tr>");
	map {$self->print("$_ ")} @{$self->{Table}};
    } else {
	$self->print("    <p>bad news: there's noone left on the team</p>\n");
    }
    if ($self->{QueryList}) {
	my $idStr = '$Id: ContactPresenter.pm,v 1.4 2004/12/30 00:30:00 eric Exp $';
	$self->print("      </table>
    <hr />
    <address><a href=\"Renaud/\">Renaud</a> and the <a href=\"../Web/\">webmaster team</a>
      <tt><a href=\"mailto:webreq\@w3.org\">&lt;webreq\@w3.org&gt;</a></tt><br />
see also: <a href=\"1999/02/10-w3m2.html\">w3m 10 Feb 1999</a><br />
made with <a href=\"http://www.php.net/\">PHP</a>
      <a href=\"Phonelist.phps\">Source code</a><br />
$idStr</address>
  </body>
</html>
");
    } else {
	$self->_readTemplate("contactFoot.xhtml");
    }
}

sub print_Exception {
    my ($self, $exception) = @_;
    my $m = $self->xmlEncode($exception->getMessage);
    $self->print("<p><strong>$m</strong></p>\n");
}

sub print_warning {
    my ($self, $message) = @_;
    $message = $self->xmlEncode($message);
    $self->print("<div class=\"warning\"><strong>Warning</strong>: $message</div>\n");
}

use HTML::Entities;

sub showMatches {
    my ($self, $results) = @_;
    foreach my $result (@$results) {
	my ($userId, $family, $given, $teamPage, $org, $title, $bday, $nick, $email, $altEmail, $phones, $domains, $bio, $image, $peoplePage) = @$result;

	my $domainList = join(',', map {$_->[0]} @$domains);
	my $rowspan = @$phones;
	my $shortEmail = $email;
	$shortEmail =~ s/\@w3.org//;
	my $akaStr = $nick ? "(a.k.a $nick)" : '';

	push (@{$self->{Index}}, "<a href=\"#$shortEmail\">$family</a>");

	push (@{$self->{Table}}, "
    <tr>
      <td valign=\"top\" rowspan=\"$rowspan\">
        <b><a href=\"$teamPage\">$family</a></b>,$given $akaStr<tt>&lt;<a name=\"$shortEmail\" href=\"mailto:$email\" id=\"$shortEmail\">$shortEmail</a>&gt;</tt><br />
        Alt Email<tt>&lt;<a href=\"mailto:$altEmail\">$email</a>&gt;</tt></td>");
	$self->renderPhone($phones->[0]);
	push (@{$self->{Table}}, "    </tr>");

	for (my $i = 1; $i < @$phones; $i++) {
	    push (@{$self->{Table}}, "    <tr>");
	    $self->renderPhone($phones->[$i]);
	    push (@{$self->{Table}}, "    </tr>");
	}
    }
}

sub renderPhone {
    my ($self, $phone) = @_;
    my ($phoneId, $number, $phonemeta, $host, $site, $note) = @$phone;

    # Figure out the best URI scheme (if any) for the "phone" number.
    my $numberStr = $number;
    if ($phonemeta =~ m/skype/i) {
	# leave alone
    } elsif ($phonemeta =~ m/(sms|mms)/i) {
	$numberStr = "<a href=\"mailto:$number\">$number</a>";
    } elsif ($number =~ m/^\+[0-9\.\-]+$/) {
	if ($phonemeta =~ m/fax/i) {
	    $numberStr = "<a href=\"fax:$number\">$number</a>";
	} else {
	    $numberStr = "<a href=\"tel:$number\">$number</a>";
	}
    }

    my $hostStr = $host eq 'Other' || $host eq '' ? '' : "<a href=\"./#$host\">$host</a>";
    my $siteColon = $hostStr && $site ? ':' : '';

    push (@{$self->{Table}}, "      <td>$phonemeta:$numberStr<br />
      $hostStr$siteColon$site</td>
      <td>$note<br />
      [<a href=\"editPhonelist?id=$phoneId\">edit</a>]</td>
    </tr>");
}

