package Combo; ###### Combo main package.
#	$Id: Combo.pm,v 1.18 2003/05/09 21:29:18 admin Exp $
#	This file is part of Combo and is licensed under the GPL and LGPL.
#	Copyright 2001-2002 by the authors.  See README and LICENSE files
#	for more details or see http://penguinsong.org/.

### Combo is the main class of the Community website kit.

#	The Combo package provides services specific to Combo-based websites.
#	In particular, it does things like expanding the  "//" in index paths.

#	Combo extends Context (q.v.) and hence provides the global entity
#	bindings and pointers to the CGI, Config, Version, Resource and User
#	objects needed to process the request.  The reason for this clumsy
#	arrangement is so that Combo can contain site-dependent overrides for
#	defaults in Context.

#	Combo also includes site-specific overrides for global functions
#	for processing files, expanding templates, and generating web pages
#	for error messages and directory listings.  All of these in Combo 
#	rely on the AMP file processor for template expansion; other sites
#	might differ.

#	Usage:  my $c = new Combo($path);
# === eventually perh. $c = new Context($path) and let the site figure out
# === which subclass to supply.

# === what else belongs in Combo:
#	Global objects:  User, Version, Process -- all might be different
#	  at other sites.
#
#	Global functions:
#	  header, footer, web page, directory formatting (all of which depend 
#	  on Process for formatting)
#	  path-to-file mappings -- depend on things like // expansion.

#	By contrast, Context wants base versions of these, .cf-file loading,
#	  and other things that don't depend on URL remapping, site policies,
#	  or file-processing techniques.
 
# === actually, should use $c = Site::Config::topContext($path)
# === and let the site file specify the context class

BEGIN {
    use Exporter();
    use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
    $cvsid = '$Id: Combo.pm,v 1.18 2003/05/09 21:29:18 admin Exp $ ';
    $cvsid =~ /,v ([0-9]+.[0-9]+)/;
    $VERSION=$1;
    @ISA = qw(Exporter Context);
    @EXPORT = ( );
}

use Context;
use Site::Config;
use AMP::Tagset;

##########################################################################
###
### Constructors:
###

### Combo->new()
#	Obtain a new Combo instance for the 
#	$path is the URL path from the request, usually from PATH_INFO
#	$trans_path is the translated path, usually from PATH_TRANSLATED
#	
sub new {
    my ($class, $path, $trans_path) = (@_);
    my $self = Context::new(@_);
    $self = bless $self, $class;
    $self->initializeCombo();
    return $self;
}

##########################################################################
###
### Access Functions:
###

sub getProcessor {
    my ($c) = @_;
    my $p;

    # === mustn't do this -- refcounts.  
    # === To make this work we would need a cleanup function.

    #$p = $c->get('_processor');
    #return $p if ref $p;

    $p = AMP::Process->new($c, $c->getPath, $c->getRealPath);

    #$c->{'_processor'} = $p; 
    return $p;
}

##########################################################################
###
### Indirect Access Functions:
###


### $c->getAreaMap
sub getAreaMap {
    my $self = shift;

    my @urls = split(" ", $self->get("area.urls"));
    my @text = split(" ", $self->get("area.text"));

    my $hash = {};
    for (my $i = @text; --$i >= 0; ) { 
	$hash->{$urls[$i]} = $text[$i]; 
    }
    return $hash;
}


##########################################################################
### 
### Path Manipulation:
###

### $c->expandIndexPath($path)
#	expand ...//... constructs in $path
#
### === has to move to Site::Config; so does inverse. ===
# === really need to test for possible one-level directory ===
#
sub expandIndexPath {
    my ($self, $path) = @_;
    my $p = "$path";
    $p =~ s|//(.)(.)|/$1/$1$2/$1$2|;
    return $p;
}


##########################################################################
### 
### Initialization:
###

### $c->findConfig()
#	Locate and read the configuration file. 
#	Set up the main configuration globals.
#
sub findConfig {
    my ($self) = (@_);

    $serverRoot = $ENV{SERVER_ROOT};
    $docRoot = $ENV{DOCUMENT_ROOT};

    # locate the site directory (COMBO_SITE_DIR, default /site)
    # Always relative to the document root.

    $siteDir = $ENV{COMBO_SITE_DIR};
    $siteDir = '/site' unless $siteDir;

    # locate the site configuration file (COMBO_SITE_CF, default site.cf)
    # in $siteDir unless it contains a slash; if it doesn't _start with_
    # a slash it's relative to the cgi directory, which allows for defaults
    # that can't be edited or viewed from the web.

    # Should really look along a path.

    $siteCF = $ENV{COMBO_SITE_CF};
    $siteCF = 'site.cf' unless $siteCF;
    $siteCF = "$docRoot$siteDir/$siteCF" unless $siteCF =~ m|/|;
    $siteCF = './site.cf' unless -f $siteCF;
}


### $c->initializeCombo()
#	Initialize a CGI.
#
sub initializeCombo {
    my ($self) = (@_);
    # Note that we have already called Context::initialize
    # so all we need here is the Combo-specific stuff.

    #$self->findConfig() unless $siteDir;

    #$self->readConfig($siteCF);
    #$templateDir = "$siteDir/templates" unless $templateDir;

    # set up areas

    # === in mod_perl, re-read $siteCF if it's changed.
}




##########################################################################
### 
### Utilities:
###


### $c->webPage($title, $text)
#	Put out a simple web page
sub webPage {
    my ($self, $title, $text) = @_;
    print $self->start_html($title);
    $self->printHeader($title);
    print $text;
    $self->printFooter();
    print "
  </body>
</html>
";
}

### $c->printHeader($title, $templateName)
#	Put out a standard header.  $templateName is the template name; 
#	if not found the default is "header".
sub printHeader {
    my ($c, $title, $tname) = (@_);
    $title = '' unless $title;
    my $path = $c->getPath;
    my $areas = $c->getAreaMap;
    my $area  = '';
    my $p = $c->getProcessor;

    if ($path =~ m|^/(.)/|) {
	$area = $areas->{$1};
    }
    
    if ($title) {}
    elsif ($path !~ m|//|) { $title = "$area Index"; }
    elsif ($c->isDir) { $title = "Index"; }
    else { $title = ""; }
    $p->{'title'} = $title;

    my $tdir = $c->getTemplateDir;
    my $t = ($tname)? "$tdir/$tname.htt" : "";
    $t = "$tdir/header.htt" unless ($tname && -f $t);

    $p->processHT($t);

    print "<p></p>\n";
}

sub printFooter {
    my ($c, $path, $tname) = (@_);
    my $p = $c->getProcessor;
    print "<p></p>\n";

    # check for dir-footer before footer
    my $tdir = $c->getTemplateDir;
    my $t = ($tname)? "$tdir/$tname.htt" : "";
    $t = "$tdir/footer.htt" unless ($tname && -f $t);
    $p->processHT($t);
}



###########################################################################
'Package loaded';
