# Copyright (c) vhffs project and its contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions 
# are met:
#
# 1. Redistributions of source code must retain the above copyright 
#   notice, this list of conditions and the following disclaimer.
#2. Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in 
#   the documentation and/or other materials provided with the 
#   distribution.
#3. Neither the name of vhffs nor the names of its contributors 
#   may be used to endorse or promote products derived from this 
#   software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
#FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
#COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
#INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
#BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.


=pod

=head1 NAME

Vhffs:Stats - Provide statistics on Vhffs Platform

=head1 SYNOPSIS

    my $main = init Vhffs::Main(...);

    my $stats = new Vhffs::Stats($main);
    my $lstcount = $stats->get_lists_in_moderation;

    # Add some lists here...
    # ...

    $stats->refresh();  # Flush cache
    my $newlstcount = $stats->get_lists_in_moderation;


=head1 METHODS

=cut


package Vhffs::Stats;

use strict;
use utf8;

use base qw(Vhffs::Object);
use Vhffs::Constants;

=pod

=head2 new

    my $stats = new Vhffs::Stats($main);

Creates a new Vhffs::Stats instance. C<$main> is
the C<Vhffs::Main> instance used to get database
connection.

=cut
sub new
{
    my ( $class , $main ) = @_;
    
    my $this = {};

    
    $this->{'main'} = $main;
    $this->{'db'} = $main->get_db_object;
    bless( $this , $class );
}

=pod

=head2 refresh

    $stats->refresh();

When you call a C<get_xxxx> method, data
are fetched from database and cached. If you
want to flush the cache, call C<refresh>.

There are very few cases where this method should
be used.

=cut

sub refresh {
    my $self = shift;
    foreach(keys(%{$self})) {
        next if($_ eq 'main' || $_ eq 'db');
        delete $self->{$_}
    }
}

=pod

=head2 get_lists_totalsubs

    my $count = $stats->get_lists_totalsubs();

Returns the count of mailing list subscribers on
the platform.

=cut

sub get_lists_totalsubs
{
    my $self = shift;
    unless(defined $self->{lists}{totalsubs}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_ml_subscribers';
        ($self->{lists}{totalsubs}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{lists}{totalsubs};
}

=pod

=head2 get_lists_in_moderation

    my $count = $stats->get_lists_in_moderation();

Returns the count of mailing lists waiting for
moderation.

=cut

sub get_lists_in_moderation
{
    my $self = shift;
    unless(defined $self->{lists}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_ml ml, vhffs_object o WHERE o.object_id=ml.object_id AND o.state='.Vhffs::Constants::WAITING_FOR_VALIDATION;
        ($self->{lists}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{lists}{awaiting_validation};
}

=pod

=head2 get_lists_in_activated

    my $count = $stats->get_lists_activated();

Returns the count of mailing lists currently activated.

=cut

sub get_lists_activated
{
    my $self = shift;
    unless(defined $self->{lists}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_ml ml, vhffs_object o WHERE o.object_id=ml.object_id AND o.state = ?';
        ($self->{lists}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )};
    }
    return $self->{lists}{activated};
}

=pod

=head2 get_lists_total

    my $count = $stats->get_lists_total();

Returns the total count of mailing lists (activated or not).

=cut

sub get_lists_total
{
    my $self = shift;
    unless(defined $self->{lists}{total}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_ml';
        ($self->{lists}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{lists}{total};
}



sub get_web_in_moderation
{
    my $self = shift;
    unless(defined $self->{web}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_httpd w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{web}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};
    }
    return $self->{web}{awaiting_validation};
}

sub get_web_activated
{
    my $self = shift;
    unless(defined $self->{web}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_httpd w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{web}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )}; 
    }
    return $self->{web}{activated};
}


sub get_user_total
{
    my $self = shift;
    unless(defined $self->{users}{total}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_users';
        ($self->{users}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{users}{total};
}


sub get_user_total_admin
{
    my $self = shift;
    unless(defined $self->{users}{total_admin}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_users WHERE admin=?';
        ($self->{users}{total_admin}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::USER_ADMIN )};
    }
    return $self->{'users'}{'total_admin'};
}


sub get_user_total_moderator
{
    my $self = shift;
    unless(defined $self->{users}{total_moderator}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_users WHERE admin=?';
        ($self->{users}{total_moderator}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::USER_MODERATOR )};
    }
    return $self->{users}{total_moderator};
}


sub get_dns_in_moderation
{
    my $self = shift;
    unless(defined $self->{dns}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_dns w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state=?';
        ($self->{dns}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};
    }
    return $self->{dns}{awaiting_validation};
}

sub get_dns_activated
{
    my $self = shift;
    unless(defined $self->{dns}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_dns w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state=?';
        ($self->{dns}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )};
    }
    return $self->{dns}{activated};
}


sub get_mail_in_moderation
{
    my $self = shift;
    unless(defined $self->{mail}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_mxdomain w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{mail}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};
    }
    return $self->{mail}{awaiting_validation};
}

sub get_mail_activated
{
    my $self = shift;
    unless(defined $self->{mail}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_mxdomain w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{mail}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )};
    }
    return $self->{mail}{activated};
}

sub get_mail_total_boxes
{
    my $self = shift;
    unless(defined $self->{mail}{total_boxes}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_boxes';
        ($self->{mail}{total_boxes}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{mail}{total_boxes};
}

sub get_mail_total_forwards
{
    my $self = shift;
    unless(defined $self->{mail}{total_forwards}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_forward';
        ($self->{'mail'}{'total_forwards'}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{mail}{total_forwards};
}

sub get_cvs_in_moderation
{
    my $self = shift;
    unless(defined $self->{cvs}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_cvs w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state=?';
        ($self->{cvs}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};
    }
    return $self->{cvs}{awaiting_validation};
}

sub get_cvs_activated
{
    my $self = shift;
    unless(defined $self->{cvs}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_cvs w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state=?';
        ($self->{cvs}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )};
    }
    return $self->{cvs}{activated};
}


sub get_svn_in_moderation
{
    my $self = shift;
    unless(defined $self->{svn}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_svn w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{svn}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};

    }
    return $self->{svn}{awaiting_validation};
}


sub get_svn_activated
{
    my $self = shift;
    unless(defined $self->{svn}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_svn w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state='.Vhffs::Constants::ACTIVATED;
        ($self->{'svn'}{activated}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{svn}{activated};
}


sub get_git_in_moderation
{
    my $self = shift;
    unless(defined $self->{git}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_git w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{git}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};

    }
    return $self->{git}{awaiting_validation};
}


sub get_git_activated
{
    my $self = shift;
    unless(defined $self->{git}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_git w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state='.Vhffs::Constants::ACTIVATED;
        ($self->{'git'}{activated}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{git}{activated};
}


sub get_mercurial_in_moderation
{
    my $self = shift;
    unless(defined $self->{mercurial}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_mercurial w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{mercurial}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};

    }
    return $self->{mercurial}{awaiting_validation};
}


sub get_mercurial_activated
{
    my $self = shift;
    unless(defined $self->{mercurial}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_mercurial w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state='.Vhffs::Constants::ACTIVATED;
        ($self->{'mercurial'}{activated}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{mercurial}{activated};
}


sub get_bazaar_in_moderation
{
    my $self = shift;
    unless(defined $self->{bazaar}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_bazaar w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{bazaar}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};

    }
    return $self->{bazaar}{awaiting_validation};
}


sub get_bazaar_activated
{
    my $self = shift;
    unless(defined $self->{bazaar}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_bazaar w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state='.Vhffs::Constants::ACTIVATED;
        ($self->{'bazaar'}{activated}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{bazaar}{activated};
}


sub get_mysql_in_moderation
{
    my $self = shift;
    unless(defined $self->{mysql}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_mysql w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{mysql}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};
    }
    return $self->{mysql}{awaiting_validation};
}

sub get_mysql_activated
{
    my $self = shift;
    unless(defined $self->{mysql}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_mysql w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{'mysql'}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )};
    }
    return $self->{mysql}{activated};
}


sub get_pgsql_in_moderation
{
    my $self = shift;
    unless(defined $self->{pgsql}{awaiting_validation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_pgsql w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{pgsql}{awaiting_validation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};

    }
    return $self->{pgsql}{awaiting_validation};
}

sub get_pgsql_activated
{
    my $self = shift;
    unless(defined $self->{pgsql}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_pgsql w INNER JOIN vhffs_object o ON o.object_id=w.object_id WHERE o.state = ?';
        ($self->{pgsql}{activated}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::ACTIVATED )};
    }
    return $self->{pgsql}{activated};
}

sub get_groups_in_moderation
{
    my $self = shift;
    unless(defined $self->{groups}{awaiting_moderation}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_groups g INNER JOIN vhffs_object o ON o.object_id=g.object_id LEFT JOIN vhffs_users u ON u.username = g.groupname WHERE o.state = ? AND u.username IS NULL';
        ($self->{groups}{awaiting_moderation}) = @{$self->{db}->selectrow_arrayref( $sql, undef, Vhffs::Constants::WAITING_FOR_VALIDATION )};
    }
    return $self->{groups}{awaiting_moderation};
}


sub get_groups_activated
{
    my $self = shift;
    unless(defined $self->{groups}{activated}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_groups g INNER JOIN vhffs_object o ON o.object_id=g.object_id LEFT JOIN vhffs_users u ON u.username = g.groupname WHERE o.state='.Vhffs::Constants::ACTIVATED.' AND u.username IS NULL';
        ($self->{groups}{activated}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{groups}{activated};
}

sub get_groups_total
{
    my $self = shift;
    unless(defined $self->{groups}{total}) {
        my $sql = 'SELECT COUNT(*) FROM vhffs_groups g LEFT JOIN vhffs_users u ON u.username = g.groupname WHERE u.username IS NULL';
        ($self->{groups}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
   }
    return $self->{groups}{total};
}

sub get_tags_categories_total
{
    my $self = shift;
    unless(defined $self->{tags_categories}{total}) {
	my $sql = 'SELECT COUNT(*) FROM vhffs_tag_category';
	($self->{tags_categories}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{tags_categories}{total};
}

sub get_tags_total
{
    my $self = shift;
    unless(defined $self->{tags}{total}) {
	my $sql = 'SELECT COUNT(*) FROM vhffs_tag';
	($self->{tags}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{tags}{total};
}

sub get_tags_used_total
{
    my $self = shift;
    unless(defined $self->{tags_used}{total}) {
	my $sql = 'SELECT COUNT(distinct tag_id) FROM vhffs_object_tag';
	($self->{tags_used}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{tags_used}{total};
}

sub get_tags_groups_total
{
    my $self = shift;
    unless(defined $self->{tags_groups}{total}) {
	my $sql = 'SELECT COUNT(distinct object_id) FROM vhffs_object_tag';
	($self->{tags_groups}{total}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{tags_groups}{total};
}

sub get_most_popular_tags
{
    my $self = shift;
    # well, I did not succeed to use $self->{tags}{most_popular}
    my $tags = [];
        my $sql = 'SELECT vhffs_tag_category.label as category, vhffs_tag.label as tag_label, COUNT(object_id) as nb_groups
                FROM vhffs_object_tag, vhffs_tag_category, vhffs_tag
                WHERE vhffs_tag.category_id=vhffs_tag_category.tag_category_id
                  AND vhffs_object_tag.tag_id=vhffs_tag.tag_id
                GROUP BY category,tag_label ORDER BY nb_groups DESC LIMIT 10';
        my $sth = $self->{db}->prepare($sql);
        $sth->execute() or return undef;
        while( (my $t = $sth->fetchrow_hashref() )  ) {
	      push @$tags, $t;
        }
    return $tags;
}

sub get_tags_groups_max
{
    my $self = shift;

    unless(defined $self->{tags_groups}{max}) {
	my $sql = 'SELECT MAX(count_tag_id) FROM (select COUNT(tag_id) as count_tag_id, object_id FROM vhffs_object_tag GROUP BY object_id) AS count_tags_groups';
	($self->{tags_groups}{max}) = @{$self->{db}->selectrow_arrayref( $sql )};
    }
    return $self->{tags_groups}{max};
}

1;


