# -------------------------------------------------------------------------------------
# MKDoc
# -------------------------------------------------------------------------------------
#
#       Author : Jean-Michel Hiver (jhiver@mkdoc.com).
#    Copyright : (c) MKDoc Holdings Ltd, 2001
# 
#      Unauthorized modification, use, reuse, distribution or redistribution
#      of this module is stricly forbidden
#
#    Description:
#
#      This module takes care of variables initialization, and then triggers each
#      plugin module until one of them handles the query
#
# -------------------------------------------------------------------------------------
package MKDoc;
use lib qw /../;
use MKDoc::System::MPH;
use Data::Dumper;
use lib::Exception;
use lib::sql::DBH;
use lib::cgi::Session;
use lib::cgi::CGI;
use flo::Editor;
use flo::HTTP::Header;
use lib::Config;
use flo::XHTMLFilter;
use flo::Template;
use lib::Template;
use lib::sql::Table;
use flo::plugin::Static;
use flo::Object;
use flo::Standard;
use lib::sql::Query;
use lib::PSP;
use flo::CGI;

use CGI;
use strict;
use vars qw /$SITES $CFG $MPH $IMPORTED $FIRST_INIT $DIR @ISA @EXPORT/;


# initializes the $DIR, $SITES and $CFG global variables, which is done
# only once on the compilation step.
BEGIN
{
    # find out where the MKDoc code base directory is, and stores that
    # information in $DIR
    my $mkdoc_base_dir = undef;
    if ($ENV{SCRIPT_FILENAME})
    {
        my @tmp = split /\//, $ENV{SCRIPT_FILENAME};
        pop @tmp;
        pop @tmp;
        $mkdoc_base_dir = join '/', @tmp;
    }
    else
    {
        $mkdoc_base_dir = '..';
    }
    $DIR = $mkdoc_base_dir;

    # load sites information from $DIR/conf/sites.conf in the $SITES
    # hashref
    my $VAR1 = undef;
    open FP, "<$DIR/conf/sites.conf";
    my $data = join '', <FP>;
    close FP;
    eval $data;
    die ($@) if (defined $@ and $@);
    $SITES = $VAR1;
    
    $CFG = undef;
    $CGI::USE_PARAM_SEMICOLONS = 1;
    
    # this will hold the names of the modules which have been imported
    $IMPORTED = {};
    
    # these should not change from one site to another
    $lib::cgi::Session::USER__NAME       = "Editor";
    $lib::cgi::Session::USER__ID         = "ID";
    $lib::cgi::Session::USER__LOGIN      = "Login";
    $lib::cgi::Session::USER__PASSWORD   = "Password";
    $lib::cgi::Session::SESSION__NAME    = "Session";
    $lib::cgi::Session::SESSION__ID      = "ID";
    $lib::cgi::Session::SESSION__TIME    = "Last_Time";
    $lib::cgi::Session::SESSION__IP      = "IP";
    $lib::cgi::Session::SESSION__USER_ID = "Editor_ID";

    $FIRST_INIT = 0;
}


##
# $class->process ($conf_file);
# -----------------------------
#   Processes this query with the modules defined in $conf_file
##
sub process
{
    my $class = shift;
    my $conf_file = shift;
    
    try
    {
	init ($conf_file);
	main();
    }
    catch
    {
	print "Content-Type: text/plain\n\n";
	print "A software error has occurred:\n";
	print "------------------------------\n\n";
	print "Dump:\n";
	print "-----\n";
	print Dumper (@_), "\n\n";
	print "SQL:\n";
	print "----\n";
	print join "\n", lib::sql::Table->query_stack;
    };
}


##
# This function makes sure that classes are properly initialized
# before we start processing. This is to ensure that class attributes
# are properly initialized when running under speedycgi or mod_perl
##
sub init
{
    my $conf_file = shift;
    
    unless (defined $FIRST_INIT and $FIRST_INIT)
    {
	# initializes the $MPH hashref which will hold information that
	# we want to be persistent
	$MPH = {};
	tie $MPH, 'MKDoc::System::MPH';
	
	# initializes the lib::Config::MPH tied hashref
	$lib::Config::MPH = {};
	tie $lib::Config::MPH, 'MKDoc::System::MPH';
	
	# initializes the lib::sql::DBH::ETERNAL hashref
	$lib::sql::DBH::ETERNAL = {};
	tie $lib::sql::DBH::ETERNAL, 'MKDoc::System::MPH';
	
	# initializes the flo::plugin::Static::MIME_TYPES tied hashref
	$flo::plugin::Static::MIME_TYPES = undef;
	tie $flo::plugin::Static::MIME_TYPES, 'MKDoc::System::MPH';
	
	$FIRST_INIT = 1;
    }
    
    # set up the base dir and config dir
    my $server_name = lc ($ENV{SERVER_NAME}) or
	throw (new lib::Exception ( code => 'SERVER_NAME_UNDEFINED',
				    info => "\$ENV{SERVER_NAME} does not seem to be defined" ) );
    
    # retrieve base directory or throw an exception
    my $base_dir = $SITES->{$server_name} or
	throw (new lib::Exception ( code => 'CANNOT_FIND_BASE_DIR',
				    info => "Base directory does not seem to be set for $server_name" ) );
    
    $lib::Config::DIR = $base_dir . '/config';
    
    # reinitializes global variables to their default values
    $flo::HTTP::Header::ACCESSOR     = undef;
    @flo::Editor::LINKS              = ();
    $flo::Editor::ETERNAL            = undef;
    $flo::Object::CONFIG             = {};
    $flo::Standard::GENERAL_CONFIG   = undef;
    $flo::XHTMLFilter::DONT_STRIP    = undef;
    $lib::cgi::CGI::CGI              = undef;
    $lib::cgi::Session::ETERNAL      = undef;
    $lib::PSP::BASE_DIR              = undef;
    $lib::Template::CONFIG           = undef;
    $lib::Template::LEFT_TOKEN       = undef;
    $lib::Template::RIGHT_TOKEN      = undef;
    $lib::Template::BASE_DIR         = undef;
    $lib::Template::TOKEN_REGEX      = undef;
    $lib::Template::STASH            = {};
    $flo::CGI::FULL_URI              = 0;
    $CGI::USE_PARAM_SEMICOLONS       = 1;
    
    # database initialization
    # $lib::sql::Query::IMPORTED       = {};
    # $lib::sql::DBH::DBH              = undef;
    # $lib::sql::DBH::ETERNAL          = undef;
    
    @lib::sql::Table::QUERY_STACK    = ();
    $lib::sql::Table::LOADED         = 0;
    
    if (defined $MPH->{DATABASE})
    {
	$lib::sql::Table::DATABASE = $MPH->{DATABASE};
	$lib::sql::Table::LOADED   = 1;
    }
    
    # load the config file
    $CFG = new lib::Config ($conf_file);
    
    # initialize the XHTMLFilter, i.e. tags which won't be stripped out
    flo::XHTMLFilter->init;
    
    # initializes template directory and delimiters
    flo::Template->init;
    
    # loads database table schemas
    lib::sql::Table->load_state ($base_dir .'/su') unless ($lib::sql::Table::LOADED);
    $MPH->{DATABASE} = $lib::sql::Table::DATABASE;
}


##
# Processes the query. Triggers the main() class method of the
# plugins in the order they were defined in the config file. Plugins
# can terminate the query processing by sending the 'TERMINATE' string
# back
##
sub main
{
    foreach my $pkg ($CFG->keys)
    {
        unless (defined $IMPORTED->{$pkg})
        {
	    my $file = $pkg;
            $file =~ s/::/\//g;
            $file .= '.pm';
	    require $file; 
	    import $pkg;
	    $IMPORTED->{$pkg} = 1;
        }

	my $ret = $pkg->main;
	last if (defined $ret and $ret eq 'TERMINATE');
    }
    if (defined $lib::sql::DBH::DBH)
    {
	$lib::sql::DBH::DBH->disconnect;
	$lib::sql::DBH::DBH     = undef;
    }
}


1;
