#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#------------------------------------------------------------
package Support::Permission;

use strict;
use warnings;
use Carp;

use lib '/app/tools/common/lib';
use Common::Assert;
use RSApache::RSWebApp;
use RSApache::Session;

use lib '/app/tools/support/lib';
use Support::DB::Item::ModuleAccess;
use Support::DB::Item::SupportRole;

sub IsAuthenticated {
    my $class = shift;

    return RSApache::RSWebApp::IsSessionValid();
}

sub CanWrite {
    my $class = shift;
    my %args  = @_;

    if ( $args{page} && $args{module} && !$args{supportRoleID} ) {
        return $class->_canWritePage(%args);
    } elsif ( $args{module} ) {
        return $class->_canWriteModule(%args);
    }

    return 0;
}

sub CanRead {
    my $class = shift;
    my %args  = @_;

    if ( $args{page} && $args{module} && !$args{supportRoleID} ) {
        return $class->_canReadPage(%args);
    } elsif ( $args{module} ) {
        return $class->_canReadModule(%args);
    }

    return 0;
}

sub _canReadModule {
    my $self = shift;
    my %args = @_;

    my $module  = $args{module};
    my $keyword = $args{keyword};

    my $userID = $args{userID} ? $args{userID} : Common::RSApp::GetActiveUserID();
    my $supportRoleID = $args{supportRoleID};

    assert($module);

    Common::Log::Debug("Permission Read Check: Module ($module)");

    return 1 if ( $module && $module eq 'DEFAULT' );

    my $returnVal;

    if ($supportRoleID) {
        $returnVal = $self->_canRoleReadModuleByRole( $supportRoleID, $module );
    } else {
        my $role = $self->_canRoleReadModule( $userID, $module );
        my $user = $self->_canUserReadModule( $userID, $module ) unless ($role);
        my $word = $self->_canAccessKeyword( $userID, $keyword );

        $returnVal = $role ? 1 : $user ? 2 : 0;
        $returnVal = undef unless ($word);
    }

    return $returnVal;
}

sub _canReadPage {
    my $self = shift;
    my %args = @_;

    my $module  = $args{module};
    my $page    = $args{page};
    my $keyword = $args{keyword};

    my $userID = $args{userID} ? $args{userID} : Common::RSApp::GetActiveUserID();

    assert($module);
    assert($page);

    Common::Log::Debug("Permission Read Check: Module ($module) Page ($page)");

    return 1 if ( $module
        && $module eq 'DEFAULT'
        && $page
        && $page eq 'DEFAULT' );

    my $role = $self->_canRoleReadPage( $userID, $module, $page );
    my $user = $self->_canUserReadPage( $userID, $module, $page ) unless ($role);
    my $word = $self->_canAccessKeyword( $userID, $keyword );

    my $returnVal = $role ? 1 : $user ? 2 : 0;
    $returnVal = undef unless ($word);

    return $returnVal;
}

sub _canRoleReadModuleByRole {
    my $self         = shift;
    my $support_role = shift;
    my $module       = shift;

    Common::Log::Debug("ROLE: $support_role");
    assert($module);

    return unless ($support_role);

    unless ( ref($support_role) ) {
        $support_role = Support::DB::Item::SupportRole->Lookup( support_role_id => $support_role );
    }

    return unless ($support_role);

    my $dbAccess = $self->_getModuleAccess( module => $module, support_role => $support_role );

    return $dbAccess && $dbAccess->can_read ? 1 : 0;
}

sub _canRoleReadModule {
    my $self         = shift;
    my $user_id      = shift;
    my $module       = shift;
    my $support_role = $self->_getSupportRole($user_id);

    Common::Log::Debug("  - Check Role Read Permission");

    return $self->_canRoleReadModuleByRole( $support_role, $module );
}

sub _canUserReadModule {
    my $self    = shift;
    my $user_id = shift;
    my $module  = shift;

    Common::Log::Debug("  - Check User Read Permission");

    assert($user_id);
    assert($module);

    my $dbAccess = $self->_getModuleAccess( user_id => $user_id, module => $module );

    return $dbAccess && $dbAccess->can_read ? 1 : 0;
}

#
# Currently only check access on a module level
#
sub _canRoleReadPage {
    my $self = shift;
    return $self->_canRoleReadModule(@_);
}

sub _canUserReadPage {
    my $self = shift;
    return $self->_canUserReadModule(@_);
}

sub _canRoleWriteModuleByRole {
    my $self         = shift;
    my $support_role = shift;
    my $module       = shift;

    Common::Log::Debug("ROLE: $support_role");
    assert($module);

    return unless ($support_role);
    unless ( ref($support_role) ) {
        $support_role = Support::DB::Item::SupportRole->Lookup( support_role_id => $support_role );
    }

    return unless ($support_role);

    my $dbAccess = $self->_getModuleAccess( module => $module, support_role => $support_role );

    return $dbAccess && $dbAccess->can_write ? 1 : 0;
}

sub _canWriteModule {
    my $self = shift;
    my %args = @_;

    my $module  = $args{module};
    my $keyword = $args{keyword};

    my $userID = $args{userID} ? $args{userID} : Common::RSApp::GetActiveUserID();
    my $supportRoleID = $args{supportRoleID};

    assert($module);

    Common::Log::Debug("Permission Write Check: Module ($module)");

    return 1 if ( $module && $module eq 'DEFAULT' );

    my $returnVal;

    if ($supportRoleID) {
        $returnVal = $self->_canRoleWriteModuleByRole( $supportRoleID, $module );
    } else {
        my $role = $self->_canRoleReadModule( $userID, $module );
        my $user = $self->_canUserReadModule( $userID, $module ) unless ($role);
        my $word = $self->_canAccessKeyword( $userID, $keyword );

        $returnVal = $role ? 1 : $user ? 2 : 0;
        $returnVal = undef unless ($word);
    }

    return $returnVal;
}

sub _canWritePage {
    my $self = shift;
    my %args = @_;

    my $module  = $args{module};
    my $page    = $args{page};
    my $keyword = $args{keyword};

    my $userID = $args{userID} ? $args{userID} : Common::RSApp::GetActiveUserID();

    assert($module);
    assert($page);

    Common::Log::Debug("Permission Write: Module ($module) Page ($page)");

    return 1 if ( $module
        && $module eq 'DEFAULT'
        && $page
        && $page eq 'DEFAULT' );

    my $role = $self->_canRoleWritePage( $userID, $module, $page );
    my $user = $self->_canUserWritePage( $userID, $module, $page ) unless ($role);
    my $word = $self->_canAccessKeyword( $userID, $keyword );

    my $returnVal = $role ? 1 : $user ? 2 : 0;
    $returnVal = undef unless ($word);

    return $returnVal;
}

sub _canRoleWriteModule {
    my $self         = shift;
    my $user_id      = shift;
    my $module       = shift;
    my $support_role = $self->_getSupportRole($user_id);

    Common::Log::Debug("  - Check Role Write Permission");

    assert($module);

    return unless ($support_role);

    my $dbAccess = $self->_getModuleAccess( user_id => $user_id, module => $module, support_role => $support_role );

    return $dbAccess && $dbAccess->can_write ? 1 : 0;
}

sub _canUserWriteModule {
    my $self    = shift;
    my $user_id = shift;
    my $module  = shift;

    Common::Log::Debug("  - Check User Write Permission");

    assert($module);

    my $dbAccess = $self->_getModuleAccess( user_id => $user_id, module => $module );

    return $dbAccess && $dbAccess->can_write ? 1 : 0;
}

#
# Currently only check access on a module level
#
sub _canRoleWritePage {
    my $self = shift;
    return $self->_canRoleWriteModule(@_);
}

sub _canUserWritePage {
    my $self = shift;
    return $self->_canUserWriteModule(@_);
}

sub _canAccessKeyword {
    my $self = shift;
    my $keyword = shift || return 1;

    Common::Log::Debug("  - Check Keyword Access ($keyword)");

    return 1;
}

sub _getSupportRole {
    my $self    = shift;
    my $user_id = shift;

    my $dbSupportUser = Support::DB::Item::SupportRole->LookupByUserID( user_id => $user_id );

    return $dbSupportUser;
}

sub _getModuleAccess {
    my $self         = shift;
    my %args         = @_;
    my $user_id      = $args{user_id};
    my $module       = $args{module};
    my $support_role = $args{support_role};

    assert($module);

    my $dbModule = ref($module) ? $module : Support::DB::Item::Module->Lookup( slug => $module );

    assert( $dbModule, "Unknown Module ($module), check the database" );

    my %access_args = ( module_id => $dbModule->module_id );

    if ($support_role) {
        $access_args{support_role_id} = $support_role->support_role_id;
    } else {
        $access_args{user_id} = $user_id;
    }

    return Support::DB::Item::ModuleAccess->Lookup(%access_args);
}

# Nobody calls these methods, which contain references to deprecated modules.
#
#sub SetSession {
#    my $class = shift;
#    my $email = shift;
#
#    assert( $email );
#
#    my $user = new User::User( email => $email );
#
#    return unless( $user );
#
#    # WHY ARE WE USING THIS DEPRECATED AND LAME ASS MODULE?
#    # AND WHY ARE WE USING USER::USER?
#    #
#    my $session = new RSApache::Session();
#    $session->Create( $user );
#
#}
#
#sub PasswordMatch {
#    my $class = shift;
#    my $email = shift;
#    my $password = shift;
#
#    return unless( $email );
#    return unless( $password );
#
#    my $userObj = new User::User( email => $email );
#
#    return unless( $userObj );
#
#    return $userObj->IsPassword($password);
#}

1;
