package RSApache::Command;

use strict;

#use warnings;

use Apache2::Directive;

use Devel::Peek;
use CGI;
use URI::Escape;
use Data::Dumper;
use Encode;

use lib '/app/tools/common/lib';
use Common::Log;
use Common::RSApp;
use RSApache::RSWebApp;
use Common::UTF8;

use RSApache::Message;

sub new {
    my ( $class, %params ) = @_;

    my $self = bless {}, $class;

    if ( $params{cgi} ) {
        $self->_paramsFromCGI( $params{cgi} );
    } else {
        $self->{params} = \%params;
    }
    return $self->_init();
}

#
# _init - VIRTUAL METHOD
#
# - Initialization routine.
#
#   Providing a default, empty base implementation. By convention,
#   subclasses should invoke their inherited _init method before
#   proceeding with their stuff.
#
#   Subclasses will find their parameters in the $self->{params} hash.
#   JPK - Normally the params would be passed to _init, but I decided
#    to stash them inside the object for Commands... The templates are
#    going to want to see the params, so I figured we might as well
#    take care of that in the base class.
#
sub _init {
    my ($self) = @_;

    $self->{xml} = {};
    $self->{xml}{Params} = $self->{params};

    $self->{xml}{App}          = RSApache::RSWebApp::GetAppName();
    $self->{xml}{Area}         = $self->area();
    $self->{xml}{Cmd}          = $self->cmd();
    $self->{xml}{Hostname}     = Common::RSApp::GetRealHostname();
    $self->{xml}{IsProduction} = Common::RSApp::IsProductionServer();

    if ( $ENV{DEV_SERVER} ) {
        $self->{xml}{DEV_SERVER} = $ENV{DEV_SERVER};
    }

    # JPK - Note that we're not logging passwords...
    #
    Common::Log::Print( "INIT COMMAND: "
          . $self->{xml}{App} . '/'
          . $self->{xml}{Area} . '/'
          . $self->{xml}{Cmd}
          . " user_id="
          . Common::RSApp::GetMasterUserID()
          . ", client_id="
          . Common::RSApp::GetClientID()
          . " PARAMS: "
          . $self->getParamsAsString( 'Form_Password' => 1, 'NewPassword' => 1, 'NewPasswordConfirm' => 1  ) );

#    Common::Log::Debug(Common::RSApp::DebugToken . " RSApache::Command::_init " . $self->requestString() . " :: params :: " . $self->getParamsAsString());

    return $self;
}

sub _paramsFromCGI {
    my ( $self, $cgi ) = @_;

    binmode( STDERR, ':utf8' );

    # !!! Add in UTF-8 conversion.
    #
    foreach my $key ( $cgi->param() ) {
        my @values;
        foreach my $value ( $cgi->param($key) ) {
            $value = Common::UTF8::Encode($value);
            push @values, $value;
        }

        # Encode as UTF-8 : CGI is too stupid to do that for us.
        #
        if ( @values > 1 ) {
            $self->{params}{$key} = \@values;
        } else {
            my $newValue = $values[0];

            # !!! JPK - Converting empty strings into undef.
            #
            if ( '' eq $newValue ) {
                $newValue = undef;
            }
            $self->{params}{$key} = $newValue;
        }
    }

    $self->{_cgi} = $cgi;

    # print STDERR Dumper($self->{params}) . "\n";
}

#
# execute -
#
# Subclasses _must_ override this method to actually do something!
#
sub execute {
    my ($self) = @_;
    return undef;
}

# Common instance methods
#
sub requestString {
    my ($self) = @_;

    if ( !$self->{_url} ) {
        my $s = ( $ENV{SERVER_PORT} eq '80' ) ? "" : "s";
        $self->{_url} = "http" . $s . "://" . $ENV{HTTP_HOST} . $ENV{REQUEST_URI};
    }

    return $self->{_url};
}

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

    my $path = $ENV{REQUEST_URI};

    my @pathArray = split( '/', $path );

    return @pathArray;

}

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

    return $self->{params};
}

sub getParam {
    my ( $self, $param ) = @_;

    return $self->{params}->{$param};
}

sub setParam {
    my ( $self, $param, $value ) = @_;

    $self->{params}->{$param} = $value;
}

sub getParamsAsString {
    my ( $self, %skip ) = @_;

    my @pairs;
    my $params = $self->getParams();
    while ( my ( $key, $value ) = each %$params ) {
        next if ( $skip{$key} );
        push @pairs, join( '=', $key, URI::Escape::uri_escape_utf8($value) );
    }

    return join( '&', @pairs );
}

# a method to generate the URI where this command can be accessed.
#
# example:
# 	/app/catalog?c=edit&AlbumID=24
#
sub getRedirect {
    my ( $self, $escaped ) = @_;

    my $cmdString = 'c=' . $self->cmd();
    my $paramString = $self->getParamsAsString( c => 1 );

    my $paramStart = '?';
    my $paramNext  = '&';
    if ($escaped) {
        $paramStart = '%3f';
        $paramNext  = '%26';
        $paramString =~ s/&/%26/g;
    }

    return '/' . $self->app() . '/' . $self->area() . $paramStart . $cmdString . $paramNext . $paramString;
}

# codes used by the template
# to display fancy messages to the user
sub addMessageXML {
    my ( $self, %args ) = @_;
    push @{ $self->{xml}{Messages}{Message} }, RSApache::Message->new(%args);
}

sub addMessage {
    my ( $self, $message ) = @_;
    push @{ $self->{xml}{Messages}{Message} }, $message;
}

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

    return 0 if ( !defined $self->{xml}{Messages}{Message} );
    return ( scalar @{ $self->{xml}{Messages}{Message} } > 0 );
}

# This returns a hash containing the 'pass-through' parameters.
# These are usually special params that the template generated, and
# that we want to preserve through a redirect.
#
# Currently our convention to identify these is for them to have a '_' prefix.
#
sub getPassThroughParams {
    my ($self) = @_;

    my %passThrough;
    foreach my $key ( keys %{ $self->{params} } ) {
        if ( '_' eq substr( $key, 0, 1 ) ) {
            $passThrough{$key} = $self->{params}{$key};
        }
    }

    return \%passThrough;
}

# This is really a hack in my opinion... but I'm hard pressed to come up with
# another way to implement file uploads, for example.
# So, don't abuse this...
#
sub getCGI {
    my ($self) = @_;
    return $self->{_cgi};
}

###
1;    # Play nicely.
###
