package AutoloadConverterScripting;

use strict;
no strict 'refs';
no strict 'subs';

use ConvertBinaryFile;

use gsprintf 'gsprintf';

# This plugin inherits from ConvertBinaryFile as a base line (so by default
# behaviour is no different to ConvertBinaryFile).  If it can find the
# plugin named in '::autoConverterScripting' then it loads this in as well
# ,setting variables visible to the outside world that indicate whether:
#    1. it found the named plugin, and
#    2. if the named plugin itself could find the necessary programs it 
#       needs to run


sub _dynamicISA 
{
    my ($autoPackage) = @_;

    my ($autoName)  = ($autoPackage =~ m/(^.*)Converter$/);
    my $autoVar     = lc($autoName);

    my $self = {};

    $self->{'_autoPackage'} = $autoPackage;
    $self->{'_autoName'}    = $autoName;
    $self->{'_autoVar'}     = $autoVar;

    # Always want this
    @AutoloadConverterScripting::ISA = ('ConvertBinaryFile' );

    # Now see if requested Converter plugin is around
    eval("require $autoPackage");
    
    if ($@) {
	# Useful debugging statement if there is a syntax error in the plugin
	print STDERR "$@\n";
	$self->{'scripting_ext_installed'} = 0;
	$self->{'scripting_ext_working'} = 0;
    }
    else {
	# Successfully found
	$self->{'scripting_ext_installed'} = 1;
	
	# now check whether it can run soffice
	if (eval "\$${autoPackage}::${autoVar}_conversion_available") {
	    $self->{'scripting_ext_working'} = 1;
	    
	} else {
	    $self->{'scripting_ext_working'} = 0;
	}
    }

    if ($self->{'scripting_ext_working'}) {
	push(@AutoloadConverterScripting::ISA, $autoPackage);
    }

    return $self;
}


my $arguments = [];

my $options = { 'name'     => "ConverterScripting",
		'desc'     => "{ConverterScripting.desc}",
		'abstract' => "yes",
		'inherits' => "yes",
		'args'     => $arguments };

####
# This plugin takes an extra initial parameter in its constructor (compared 
#   with the norm).  The extra parameter specifies which plugin it should 
#   try to dynamically load
#####

sub new {
    my ($class) = shift (@_);
    my ($autoPackage, $pluginlist,$inputargs,$hashArgOptLists) = @_;
    push(@$pluginlist, $class);

    my $dynamic_self = _dynamicISA($autoPackage);
    my $autoName = $dynamic_self->{'_autoName'};
    my $autoVar  = $dynamic_self->{'_autoVar'};

    if ($dynamic_self->{'scripting_ext_installed'}) {
	my ($cpackage,$cfilename,$cline,$csubr,$chas_args,$cwantarray) = caller(0);

	print STDERR "$class: $autoName Extension to Greenstone detected for $cpackage\n";
	if ($dynamic_self->{'scripting_ext_working'}) {
	    # print STDERR "... and it appears to be working\n";
	} else {
	    print STDERR "... but it appears to be broken\n";
	    &gsprintf(STDERR, "AutoloadConverter: {AutoloadConverter.noconversionavailable}");

	    my $dictentry_reason
		= eval "$autoPackage\.\$${autoPackage}::no_${autoVar}_conversion_reason";

	    &gsprintf(STDERR, " ({$dictentry_reason})\n");
	}
    }

    if ($dynamic_self->{'scripting_ext_working'}) {

	my $opt_scripting_args = 
	    [ { 'name' => "$autoVar\_scripting",
		'desc' => "{$autoPackage.$autoVar\_scripting}",
		'type' => "flag",
		'reqd' => "no" } ];

	push(@$arguments,@$opt_scripting_args);
    }

    push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
    push(@{$hashArgOptLists->{"OptList"}},$options);

    my $self;
    if ($dynamic_self->{'scripting_ext_working'}) {
	
	my $autoc_self = eval "new $autoPackage(\$pluginlist, \$inputargs, \$hashArgOptLists,1);";
	my $cbf_self = new ConvertBinaryFile($pluginlist, $inputargs, $hashArgOptLists);
	$self = BasePlugin::merge_inheritance($dynamic_self,$autoc_self, $cbf_self);

	$self->{"{$autoVar}_available"} = 1;
    }
    else {
	$self = new ConvertBinaryFile($pluginlist, $inputargs, $hashArgOptLists);
	$self->{"{$autoVar}_available"} = 0;
   }

    return bless $self, $class;
}

sub init {
    my $self = shift (@_);
    my ($verbosity, $outhandle, $failhandle) = @_;
    my $autoPackage = $self->{'_autoPackage'};

    $self->SUPER::init($verbosity,$outhandle,$failhandle);
    if ($self->{'scripting_ext_working'}) {
	eval "\$self->${autoPackage}::init();";
    }
}

sub begin {
    my $self = shift (@_);
    my $autoPackage = $self->{'_autoPackage'};

    if ($self->{'scripting_ext_working'}) {
	eval "\$self->${autoPackage}::begin(\@_);";
    }
    $self->SUPER::begin(@_);
}

sub deinit {
    # called only once, after all plugin passes have been done
    my ($self) = @_;
    my $autoPackage = $self->{'_autoPackage'};

    if ($self->{'scripting_ext_working'}) {
	eval "\$self->${autoPackage}::deinit()";
    }
    $self->SUPER::deinit();
}

# if the dynamically loaded Converter plugins is working, and scripting is on,, then call its convert
# method, otherwise fall back to ConvertBinaryFile method.

sub tmp_area_convert_file {
    my $self = shift (@_);
    my ($output_ext, $input_filename, $textref) = @_;
    my $autoPackage = $self->{'_autoPackage'};
    my $autoVar = $self->{'_autoVar'};
    my $autoName = $self->{'_autoName'};

    if ($self->{'scripting_ext_working'} && $self->{"${autoVar}_scripting"}) {
	my ($result, $result_str, $new_filename) 
	    = eval "\$self->${autoPackage}::convert(\$input_filename, \$output_ext);";
	if ($result != 0) {
	    return $new_filename;
	}
	my $outhandle=$self->{'outhandle'};
	print $outhandle "$autoName Conversion error\n";
	print $outhandle $result_str;
	return "";
    }
    else {
	return $self->ConvertBinaryFile::tmp_area_convert_file(@_);
    }
}
