package AppUser::User::UserAccess;

use strict;
use warnings;
use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Assert;
use Common::Client;

use lib '/app/tools/appuser/lib';
use AppUser::DB::Item::AccessLevel;
use AppUser::DB::Item::User;
use AppUser::DB::Item::UserAccess;
use AppUser::DB::Item::UserClientLabelMap;
use AppUser::DB::Item::UserClientImprintMap;
use AppUser::DB::Item::UserClientPublisherMap;

use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::PublisherImprints;

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Label;
use Common::FormObject;
use base 'Common::FormObject';

use constant kRSAdmin         => 1;    # ACCESS_RSADMIN
use constant kRSRep           => 2;    # ACCESS_RSREP
use constant kClientAdmin     => 3;    # ACCESS_CLIENTADMIN
use constant kClientRep       => 4;    # ACCESS_CLIENTREP
use constant kClientUser      => 5;    # ACCESS_CLIENTUSER
use constant kClientMarketing => 6;    # ACCESS_CLIENTMARKETING

sub _init {
    my ( $self, %args ) = @_;

    $self->SUPER::_init(%args);

    my %properties;

    if ( $args{_dbItem} ) {
        $self->_propertiesFromDBItem( \%properties, $args{_dbItem} );
    } elsif ( $args{userID} ) {
        $self->_propertiesFromDB( \%properties, $args{userID} );
    } else {
        $self->_propertiesFromDefaults( \%properties );
    }

    $self->_initProperties( \%properties );

    #$self->_initSubs(\%properties);

    return $self;
}

sub _propertiesFromDB {
    my ( $self, $props, $userID ) = @_;

    my $clientID = Common::RSApp->GetClientID();
    my $dbItem = AppUser::DB::Item::UserAccess->Lookup( user_id => $userID );

    if ($dbItem) {
        $self->_propertiesFromDBItem( $props, $dbItem );
    } else {
        $self->_propertiesFromDefaults($props);
    }
}

sub _propertiesFromDBItem {
    my ( $self, $props, $dbItem ) = @_;
    assert($props);
    assert($dbItem);
    $props->{user_id}      = $dbItem->user_id;
    $props->{client_id}    = $dbItem->client_id;
    $props->{access_level} = $dbItem->access_level;

    #$props->{label_id}		= $dbItem->label_id;
}

sub _propertiesFromDefaults {
    my ( $self, $props ) = @_;

    $props->{client_id} = Common::RSApp->GetClientID();
}

sub _initProperties {
    my ( $self, $props ) = @_;

    $self->{UserID}      = Common::FormObject::Scalar->new( value => $props->{user_id} );
    $self->{ClientID}    = Common::FormObject::Scalar->new( value => $props->{client_id} );
    $self->{AccessLevel} = Common::FormObject::Scalar->new( value => $props->{access_level}, required => 1 );

    # Fill in ye olde list of label ids (and now, imprint ids (and now, also publisher ids))
    #
    my @labelIDs;
    my @imprintIDs;
    my @publisherIDs;
    if ( $props->{user_id} ) {
        my $labelCollection = AppUser::DB::Item::UserClientLabelMap->GetByUserIDClientID( $props->{user_id}, $props->{client_id} );
        while ( $labelCollection->hasNext() ) {
            my $obj     = $labelCollection->next();
            my $labelID = $obj->label_id;
            push @labelIDs, $labelID;
        }

        if ( $self->AccessLevel() == AppUser::DB::Item::AccessLevel::kImprintView ) {
            my $imprintCollection = AppUser::DB::Item::UserClientImprintMap->GetByUserIDClientID( $props->{user_id}, $props->{client_id} );
            while ( $imprintCollection->hasNext() ) {
                my $obj       = $imprintCollection->next();
                my $imprintID = $obj->imprint_id;
                push @imprintIDs, $imprintID;
            }
        }

        if ( $self->AccessLevel() == AppUser::DB::Item::AccessLevel::kPublisherView ) {
            my $publisherCollection =
              AppUser::DB::Item::UserClientPublisherMap->GetByUserIDClientID( $props->{user_id}, $props->{client_id} );
            while ( $publisherCollection->hasNext() ) {
                my $obj         = $publisherCollection->next();
                my $publisherID = $obj->publisher_id;
                push @publisherIDs, $publisherID;

                # Going to add the imprints for each publisher to the imprint list.
                # This should allow us to the filter the list for users who only have access to some publishers.
                #
                # But only for BookPub clients!
                my $client = Common::Client::Current();
                if ( $client->isClientType(Common::Client::kBookPublishing) ) {
                    my $publisherImprintCollection = BookPub::DB::Item::PublisherImprints->GetAllByPublisherID($publisherID);
                    while ( $publisherImprintCollection->hasNext() ) {
                        my $obj       = $publisherImprintCollection->next();
                        my $imprintID = $obj->imprint_id;
                        push @imprintIDs, $imprintID;
                    }
                }
            }
        }
    }

    $self->{LabelID}     = \@labelIDs;
    $self->{ImprintID}   = \@imprintIDs;
    $self->{PublisherID} = \@publisherIDs;
}

sub getLabelIDs {
    my ($self) = @_;
    return $self->{LabelID};
}

sub getImprintIDs {
    my ($self) = @_;
    return $self->{ImprintID};
}

sub getPublisherIDs {
    my ($self) = @_;
    return $self->{PublisherID};
}

sub validate {
    my ($self) = @_;

    my $valid = $self->SUPER::validate();

    if ($valid) {

        # there are some rules about setting access_level:
        #
        # 	1. users set to be CLIENT USERS must have a label associated with them.
        # 		- check for access level == ClientUser
        # 		- get all labels
        #
        #		if(kClientUser == $self->AccessLevel())
        #		{
        #			my $labelCollection = RPS::DB::Item::Label->GetAll();
        #			if($labelCollection->size() > 1)
        #			{
        #				if(! $self->LabelID())
        #				{
        #					$self->{LabelID}->setError(Common::FormObject::kErrFieldBlank);
        #					$valid = 0;
        #				}
        #			}
        #		}
        #		else
        #		{
        #			$self->LabelID(undef);
        #		}
    }

    return $valid;
}

sub LabelID {
    my $self = shift;

    if (@_) {
        my $newVal = shift @_;
        if ( ref($newVal) eq 'ARRAY' ) {
            $self->{LabelID} = $newVal;
        } else {
            $self->{LabelID} = [$newVal];
        }
    } else {
        return $self->{LabelID};
    }

    #print STDERR "LABELID: " . Dumper($self->{LabelID}) . "\n";
}

sub ImprintID {
    my $self = shift;

    if (@_) {
        my $newVal = shift @_;
        if ( ref($newVal) eq 'ARRAY' ) {
            $self->{ImprintID} = $newVal;
        } else {
            $self->{ImprintID} = [$newVal];
        }
    } else {
        return $self->{ImprintID};
    }

    #print STDERR "LABELID: " . Dumper($self->{LabelID}) . "\n";
}

sub PublisherID {
    my $self = shift;

    if (@_) {
        my $newVal = shift @_;
        if ( ref($newVal) eq 'ARRAY' ) {
            $self->{PublisherID} = $newVal;
        } else {
            $self->{PublisherID} = [$newVal];
        }
    } else {
        return $self->{PublisherID};
    }
}

sub save {
    my ($self) = @_;

    # -------------------------------
    # Save myself
    # -------------------------------
    #
    my $new = 0;
    my $dbItem = AppUser::DB::Item::UserAccess->Lookup( user_id => $self->UserID(), client_id => $self->ClientID() );
    if ( !$dbItem ) {
        $new    = 1;
        $dbItem = AppUser::DB::Item::UserAccess->Create();

        # $dbItem->client_id(Common::RSApp->GetClientID());
        $dbItem->client_id( $self->ClientID() );
    }

    $dbItem->user_id( $self->UserID() );
    $dbItem->access_level( $self->AccessLevel() );

    #	$dbItem->label_id($self->LabelID());

    $dbItem->save();

    # Delete the old label map (if any), and create the new one (if any)
    #
    AppUser::DB::Item::UserClientLabelMap->DeleteByUserIDClientID( $dbItem->user_id, $self->ClientID );
    foreach my $labelID ( @{ $self->{LabelID} } ) {
        my $newMapItem = AppUser::DB::Item::UserClientLabelMap->Create(
            user_id   => $dbItem->user_id,
            client_id => $self->ClientID,
            label_id  => $labelID,
        );
        $newMapItem->save();
    }

    # Delete the old imprint map (if any), and create the new one (if any)
    #
    AppUser::DB::Item::UserClientImprintMap->DeleteByUserIDClientID( $dbItem->user_id, $self->ClientID );
    foreach my $imprintID ( @{ $self->{ImprintID} } ) {
        my $newMapItem = AppUser::DB::Item::UserClientImprintMap->Create(
            user_id    => $dbItem->user_id,
            client_id  => $self->ClientID,
            imprint_id => $imprintID,
        );
        $newMapItem->save();
    }

    # Delete the old publisher map (if any), and create the new one (if any)
    #
    AppUser::DB::Item::UserClientPublisherMap->DeleteByUserIDClientID( $dbItem->user_id, $self->ClientID );
    foreach my $publisherID ( @{ $self->{PublisherID} } ) {
        my $newMapItem = AppUser::DB::Item::UserClientPublisherMap->Create(
            user_id      => $dbItem->user_id,
            client_id    => $self->ClientID,
            publisher_id => $publisherID,
        );
        $newMapItem->save();
    }

    if ($new) {
    }

    # reload object
    #
    $self->_init( _dbItem => $dbItem );
}

###
1;    # Play nicely.
###
