package XXV::MODULES::REPORT;

use strict;

use Tools;
use Locale::gettext;


# This module method must exist for XXV
# ------------------
sub module {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $args = {
        Name => 'REPORT',
        Prereq => {
            # 'Perl::Module' => 'Description',
        },
        Description => gettext('This module read in every module the status information and display this. Also this module send this informations e.g. as mail report.'),
        Version => '0.01',
        Date => '19.04.2005',
        Author => 'xpix',
        Level => 'user',
        Preferences => {
            active => {
                description => gettext('Activate this service'),
                default     => 'y',
                type        => 'confirm',
                required    => gettext('This is required!'),
            },
            interval => {
                description => gettext('Time in hours to send the report.'),
                default     => 6,
                type        => 'integer',
                required    => gettext('This is required!'),
            },
            host => {
                description => gettext('Used host of referred link inside reports.'),
                default     => main::getModule('STATUS')->name,
                type        => 'host',
            },
        },
        Commands => {
            report => {
                description => gettext("Display the report screen 'modname'"),
                short       => 'rp',
                callback    => sub{ $obj->report(@_) },
            },
            request => {
                description => gettext("Display the actual news site 'typ'"),
                short       => 'req',
                callback    => sub{ $obj->request(@_) },
            },
        },
    };
    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;

    # the big Config
    $self->{CONFIG} = $attr{'-config'};

    # the dbh 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}};

    $self->{LastReportTime} = time;

    # Interval to send report
    Event->timer(
        interval => $self->{interval}*3600,
        prio => 6,  # -1 very hard ... 6 very low
        cb => sub{
            $self->report();
            $self->{LastReportTime} = time;
        },
    );

    # The Initprocess
    my $erg = $self->init or return error('Problem to initialze Module');

    # Initiat after load modules ...
    main::after(sub{
        my $start = main::getStartTime;
        $self->news(
            sprintf(gettext('Restart the xxv system at: %s!'), datum($start,'voll')),
            undef,
            undef,
            undef,
            'important',
        );
    }, "Send restart Message to News channel ...");

	return $self;
}

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

    # Load the NEWS Plugins ...
    my @mods = glob($obj->{paths}->{NEWSMODS}.'/*.pm');

    # Try to use the news plugins
    foreach my $module (reverse @mods) {
        my $moduleName = 'XXV::OUTPUT::NEWS::'.(split('\.',(split('/', $module))[-1]))[0];

        # make an object for the module
	    eval "use $moduleName";
        error $@ if $@;
        my $mod = $moduleName->new(
            -config => $obj->{CONFIG},
            -dbh    => $obj->{dbh},
            -paths  => $obj->{paths},
            -host  => $obj->{host},
        );

        unless($mod) {
            error('Problem to load Module %s!',$moduleName);
            next;
        }

        $obj->{NEWSMODS}->{$moduleName} = $mod;

        main::addModule($moduleName, $obj->{NEWSMODS}->{$moduleName});

        debug sprintf("Load NEWS Module %s = %s\n",
            $moduleName,
            (ref $obj->{NEWSMODS}->{$moduleName})
                ? $obj->{NEWSMODS}->{$moduleName}->{MOD}->{Version}
                : 'Problem!');
    }

    return 1;
}


# ------------------
sub report {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $watcher = shift;
    my $console = shift;
    my $modulename = shift || '';

    my $mods = main::getModules();

    # Look for status entry in modCfg and call his
    my $result = {};
    foreach my $modName (sort keys %{$mods}) {
        my $modCfg = $mods->{$modName}->{MOD};
        next if($modulename and uc($modulename) ne $modCfg->{Name});
        if(exists $modCfg->{Status} and ref $modCfg->{Status} eq 'CODE') {
            $result->{$modCfg->{Name}} = $modCfg->{Status}($watcher, $console, $obj->{LastReportTime});
        }
    }

    $console->table($result, {hide_HeadLine => 1, hide_HeadRow => 1, maxwidth => 80})
        if(ref $console);

    return 1;
}

# ------------------
sub news {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $title = shift || return error ('No Title!' );
    my $text  = shift || '';
    my $cmd   = shift || '';
    my $id    = shift || '';
    my $levname  = shift || 'harmless'; # Level for how important is this news?

    # convert Levelname to integer
    my $lev   = $obj->scala($levname)
        || return error('Problem to analyze Level!');

    my  $url = sprintf("http://%s:%s/", $obj->{host}, main::getModule('HTTPD')->{Port});
        $url = sprintf("%s?cmd=%s&data=%s", $url, $cmd, $id)
            if($cmd);

    my $news = {
        AddDate => time,
        Title   => $title,
        Text    => $text,
        Cmd     => $cmd,
        Id      => $id,
        Url     => $url,
        Level   => $lev,
        LevelName => $levname,
    };

    # Send to all activated News modules
    foreach my $modName (sort keys %{$obj->{NEWSMODS}}) {

        # Active?
        next if($obj->{NEWSMODS}->{$modName}->{active} ne 'y');

        # Level correct?
        next if(exists $obj->{NEWSMODS}->{$modName}->{level}
                and $obj->{NEWSMODS}->{$modName}->{level} >= $lev);

        # Do to send (first read and then send)
        $obj->{NEWSMODS}->{$modName}->read($news);
    }

}

# ------------------
sub request {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $watcher = shift || return error ('No Watcher!' );
    my $console = shift || return error ('No Console!' );
    # To this time you can set on
    # cmd=request&data=rss&ver=2 or
    # cmd=request&data=mail
    # ...
    my $typ = shift || return error ('No Typ!' );
    my $params = shift || {};

    my ($mod) = grep(/${typ}$/i, keys %{$obj->{NEWSMODS}});

    return $console->message(sprintf(gettext("Sorry, but this type '%s' does not exist on this system!"), $typ))
        unless($mod);

    return $console->message(gettext("Sorry, but this module is not active!"))
        unless($obj->{NEWSMODS}->{$mod}->{active} eq 'y');

    $console->{noFooter} = 1;

    return $console->out(
        $obj->{NEWSMODS}->{$mod}->req($params),
        $obj->{NEWSMODS}->{$mod}->{TYP}
    );
}


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

    $obj->{SCALA} = {
        'harmless'      => 10,
        'intresting'    => 30,
        'veryintresting'=> 50,
        'important'     => 70,
        'veryimportant' => 100,
    } unless(exists $obj->{SCALA});

    if($typ and exists $obj->{SCALA}->{$typ}) {
        return $obj->{SCALA}->{$typ};
    } else {
        return error("The Level %s does not exist! Please use %s", $typ, join(',', keys %{$obj->{SCALA}}));
    }
}


1;
