package Common::DB::Item::Permission;

use strict;
use warnings;

use lib '/app/tools/common/lib';
use Common::DB::ItemCollection;
use Common::DB::Item;
use base 'Common::DB::Item';

use constant kTable => 'permission';
use constant kDB    => Common::DB::Item::kCommonDB();

# This is a filtered accessor.
# You can specify area, command, app, access_level, da_allowed, la_allowed (in any combination)
#
sub GetPermissions {
    my ( $class, %args ) = @_;

    my $dbo = Common::RSApp::GetCommonDB();

    my $sql = 'SELECT * FROM ' . kTable;

    my @extraArgs;
    if ( $args{app} ) {
        push @extraArgs, "application=" . $dbo->DBQuote( $args{app} );
    }
    if ( $args{area} ) {
        push @extraArgs, "area=" . $dbo->DBQuote( $args{area} );
    }
    if ( $args{command} ) {
        push @extraArgs, "command=" . $dbo->DBQuote( $args{command} );
    }
    if ( exists $args{clientTypeMask} ) {

        # the 'allow' and 'deny' masks are interpreted slightly differently...
        #
        # allow: if _all_ the bits are set in the clientTypeMask, allow access.
        #        Usually there is just 1 bit set, but this allows us to have
        #        'hybrid' commands that are available only to clients that have
        #        a combination of features available.
        # deny: if _any_ of the bits are set in the clientTypeMask, deny access.
        #       Again, usually there is just 1 bit set.
        #
        #        push @extraArgs, "(allow_client_type & ".$args{clientTypeMask}.") = allow_client_type";
        push @extraArgs, "allow_client_type & " . $args{clientTypeMask} . "";
        push @extraArgs, "! (deny_client_type & " . $args{clientTypeMask} . ')';
    }

    if ( scalar @extraArgs ) {
        $sql .= " WHERE " . join( ' AND ', @extraArgs );
    }

    $sql .= ' ORDER BY application,area,command';

    #print STDERR "SQL: $sql\n";
    Common::Log::Debug("QUERY: $sql");

    my $collection = Common::DB::ItemCollection->new(
        class => "Common::DB::Item::Permission",
        query => $sql,
        dbID  => kDB,
    );

    return $collection;
}

# These routines won't return DBItem collections.
# They instead just return arrays of strings.
#
sub _getDistinctColumn {
    my ($column) = @_;
    my $dbo      = Common::RSApp::GetCommonDB();
    my $sql      = "SELECT DISTINCT $column FROM " . kTable;

    my $sth = $dbo->DoCmd($sql);
    my @outArray;
    while ( my $col = $sth->fetchrow() ) {
        push @outArray, $col;
    }

    return @outArray;
}

sub GetApplications {
    return _getDistinctColumn('application');
}

sub GetAreas {
    return _getDistinctColumn('area');
}

sub GetCommands {
    return _getDistinctColumn('command');
}

1;

