package XXV::MODULES::SHARE;
use strict;

use Tools;
use Locale::gettext;
use vars qw($AUTOLOAD);


$SIG{CHLD} = 'IGNORE';

# ------------------
sub AUTOLOAD {
# ------------------
    my $obj = shift || return error ('No Object!' );

    my $cmd = (split('::', $AUTOLOAD))[-1];
    return  if($cmd eq 'DESTROY');

    # Den Hash per Hand nachpflegen
    # bis zum nächsten Refresh ...
    if($cmd eq 'setEventLevel' and exists $obj->{EventLevels} and ref $obj->{EventLevels} eq 'HASH') {
        $obj->{EventLevels}->{$_[0]}->{Level} = $_[1];
    }

    if($obj->{SOAP} && $obj->{active} eq 'y') {
        my $erg = $obj->CmdToSoap($cmd, $obj->{SessionId}, @_);
        return $erg;
    }
}


# This module method must exist for XXV
# ------------------
sub module {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $args = {
        Name => 'SHARE',
        Prereq => {
            'SOAP::Lite' => 'Client and server side SOAP implementation.',
        },
        Description => gettext('This module send and read shared data from SOAP Server.'),
        Version => '0.02',
        Date => '19.02.2006',
        Author => 'xpix',
        Preferences => {
            active => {
                description => gettext('Activate this service'),
                default     => 'n',
                type        => 'confirm',
                required    => gettext('This is required!'),
            },
            uri => {
                description => gettext('The uri identifies the class on the server. The url (with port) for the XXV-SOAP-Server Address.'),
                default     => 'http://xpix.dyndns.org:81/XXV/Server',
                type        => 'url',
                required    => gettext('This is required!'),
            },
            proxy => {
                description => gettext('The proxy identifies the CGI script that provides access to the class, Is simply the address of the server to contact that provides the methods.'),
                default     => 'http://xpix.dyndns.org:81/',
                type        => 'url',
                required    => gettext('This is required!'),
            },
            interval => {
                description => gettext('The interval in seconds to get shared data.'),
                default     => 300,
                type        => 'integer',
                required    => gettext('This is required!'),
            },
        },
        Commands => {
            topten => {
                description => gettext("Display the TopTen list."),
                short       => 't10',
                callback    => sub{ $obj->TopTen(@_) },
            },
        },
    };
    return $args;
}

# ------------------
sub new {
# ------------------
	my($class, %attr) = @_;
	my $self = {};
	bless($self, $class);

    # paths
    $self->{paths} = delete $attr{'-paths'};

	# who am I
    $self->{MOD} = $self->module;

    # read the DB Handle
    $self->{dbh} = delete $attr{'-dbh'};

    # all configvalues to $self without parents (important for ConfigModule)
    map {
        $self->{$_} = $attr{'-config'}->{$self->{MOD}->{Name}}->{$_};
        $self->{$_} = $self->{MOD}->{Preferences}->{$_}->{default} unless($self->{$_});
    } keys %{$self->{MOD}->{Preferences}};

    # Try to use the Requirments
    map {
        eval "use $_";
        return panic("\nCan not load Module: $_\nPlease install this module on your System:\nperl -MCPAN -e 'install $_'") if($@);
    } keys %{$self->{MOD}->{Prereq}};

    # The Initprocess
    $self->_init or return error('Problem to initialze Module');

	return $self;
}

# ------------------
sub _init {
# ------------------
    my $obj = shift || return error ('No Object!' );

    $obj->{SessionId} = $obj->generateUniqueId
        unless($obj->{SessionId});

    # Connect To SOAP Server ...
    $obj->{SOAP} = $obj->ConnectToSOAP($obj->{SessionId});
    unless($obj->{SOAP}) {
        debug('SOAP Server %s can not connected!', $obj->{uri});
        debug('Deactivate the Share Modul!');
        $obj->{active} = 'n';
        return 1;
    }

    $obj->{EventLevels} = $obj->getEventLevels();

    # Interval to read timers and put to DB
    Event->timer(
        interval => $obj->{interval},
        prio => 6,  # -1 very hard ... 6 very low
        cb => sub{
            lg 'Start interval share to get for Levels!';
            $obj->{EventLevels} = $obj->getEventLevels();
        },
    ) if($obj->{active} eq 'y');

    return 1;
}

# ------------------
sub generateUniqueId {
# ------------------
    my $obj = shift  || return error ('No Object!' );

    my $sessionId;
	for(my $i=0 ; $i< 16 ;)
	{
		my $j = chr(int(rand(127)));

		if($j =~ /[a-zA-Z0-9]/)
		{
			$sessionId .=$j;
			$i++;
		}
	}
    return $sessionId;
}

# ------------------
sub ConnectToSOAP {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $sid = shift  || $obj->{SessionId} || return error ('No SesionID!' );
    my $uri = shift  || $obj->{uri};
    my $prx = shift  || $obj->{proxy};

    return undef
        if($obj->{active} ne 'y');

    $obj->{SOAP} = SOAP::Lite
		->uri($uri)
		->proxy($prx, timeout => 5)
		->on_fault(sub{});

    my $usrkey = $obj->CmdToSoap('getUsrKey');
    return $obj->{SOAP};
}

# ------------------
sub getEventLevel {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $eid = shift  || return;

    return unless($obj->{EventLevels});

    return $obj->{EventLevels}->{$eid}->{Level}
        if(exists $obj->{EventLevels}->{$eid});
}

# ------------------
sub TopTen {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $watcher = shift || return error ('No Watcher!');
    my $console = shift || return error ('No Console');
    my $anzahl = shift || 10;

    my $data = $obj->getTopTen($anzahl);

    my $epg = main::getModule('EPG');
    my $tim = main::getModule('TIMERS');
    my $can = main::getModule('CHANNELS');

    my @fields = ('eventid','title','subtitle','description','channel_id','starttime','video','audio');

    my $out = [];
    foreach my $entry (@$data) {
            my $edata = $epg->getId($entry->[0], );
            next unless(ref $edata eq 'HASH');
            push(@$out, [ @fields, 'Rank', '__Level', '__Count' ])
                unless(scalar @$out);
            my @val = map { $edata->{$_} } @fields;
            push(@$out, [ @val, $entry->[3], $entry->[1],$entry->[2] ]);
        }

    return $console->table($out, {
        channels => $can->ChannelHash('Id'),
        timers => $tim->getEpgIds
       });
}

# ------------------
sub CmdToSoap {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $cmd = shift  || return error ('No Command!' );
    my @arg = @_;

    $obj->{CAN}->{$cmd} = $obj->{SOAP}->can($cmd)
        unless(exists $obj->{CAN}->{$cmd});

    my $res = eval "\$obj->{SOAP}->$cmd(\@arg)";
    $@ ? return error('SyntaxError: $@') :
        defined($res) && $res->fault ?
            return error('Fault %s-%s', $res->faultcode, $res->faultstring) :
                !$obj->{SOAP}->transport->is_success ?
                    return error('Transport Error: %s', $obj->{SOAP}->transport->status) :
                        return $res->result;
}

1;
