package LIMS::Controller::Admin::User;

use strict;

use base 'LIMS::Controller::Admin';
use LIMS::Local::Utils;

__PACKAGE__->authz->authz_runmodes(	':all' => 'do_admin' );

#-------------------------------------------------------------------------------
sub default : StartRunmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    my $errs = shift;

	my $model = $self->model('User');

    my %data = (
        users     => $model->get_all_users({sort_by => 'username'}),
        groups    => $model->get_user_groups({sort_by => 'group_label'}),
        locations => $model->get_user_locations({sort_by => 'location_name'}),
    );

    if ( my $id = $self->param('id') || $self->query->param('id') ) {
        # get user details:
        my $this_user_details = $self->_get_user_details($id);
			# $self->debug([keys %$user_details]);

        # load this users details into %data:
        map {
            $data{$_} = $this_user_details->{$_};
        } keys %$this_user_details;
    }

    map $self->tt_params($_ => $data{$_}), keys %data;
		# $self->debug([ keys %data ]);

    # get js validation foo_onsubmit & foo_dfv_js vars into template:
    $self->js_validation_profile('user_details');

    return $self->tt_process($errs);
}

#-------------------------------------------------------------------------------
# used to create new user and to update existing user details:
sub update_user_details : Runmode { 
    my $self = shift; $self->_debug_path($self->get_current_runmode);

	my $user_id = $self->param('id');
	
	# put id (if submitted) into params() for validate('user_details') profile:	
    if ( $user_id ) { # warn $user_id;
        $self->query->param( _record_id => $user_id );
    }

	my $dfv = $self->check_rm('default', $self->validate('user_details') )
	|| return $self->dfv_error_page;

	my $data = $dfv->valid
	|| return $self->forward('default'); # eg if empty param; # $self->debug($data);

	if ($user_id) {
		# provide 'id' if supplied, so record updated, otherwise new one created: 
		$data->{id} = $user_id;
		
		# load existing user (if it's an 'update user' action):
		my $user = $self->model('User')->get_user_profile($user_id)
    	|| return $self->error("Cannot retreive user details for id=$user_id");
		
		# check if password has been changed - if form pwd not same as retrieved
		# pwd, must have been changed & will need encrypting:
		if ($data->{password} ne $user->password) {
			# encrypt password using SHA1 (or MD5):
			my $sha1 = LIMS::Local::Utils::sha1_digest($data->{password});
			$data->{password} = $sha1; # $self->debug('sha1:'.$sha1);
		}
		# set message:
		$self->stash( user_update_action => 'edit_success' );
	}
	# it's a 'create new user' action, so encrypt password:
	else { # warn 'here';
		my $sha1 = LIMS::Local::Utils::sha1_digest($data->{password});
		$data->{password} = $sha1; # $self->debug('sha1:'.$sha1);
		# set message:
		$self->stash( user_update_action => 'create_success' );
	}

    my $rtn = $self->model('User')->update_user($data);

	if ( $rtn ) {
        $self->error($rtn);
	}
	else { # redirect after db edit:
		# set MessageStack msg set above:
		my $action = $self->stash->{user_update_action};
		$self->flash( info => $self->messages('admin')->{user}->{$action} );
        $self->redirect( $self->query->url . '/admin/user/default/'.$user_id );
	}
}

#-------------------------------------------------------------------------------
sub edit_permissions : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);

    my $id = $self->param('id')
	|| return $self->error( 'no id passed to '.$self->get_current_runmode );

    my $data = $self->_get_user_details($id);

    map $self->tt_params($_ => $data->{$_}), keys %$data;

    return $self->tt_process('admin/user/edit_permissions.tt');
}

#-------------------------------------------------------------------------------
sub reset_user_permissions : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);

    my $id = $self->param('id')
	|| return $self->error( 'no id passed to '.$self->get_current_runmode );

    my $user = $self->model('User')->get_user_profile($id);

    $self->tt_params( user => $user );

    # need confirmation before resetting permissions:
    return $self->tt_process('admin/user/reset_permissions.tt')
        unless $self->query->param('confirm_reset');

    my $rtn = $self->model('User')->delete_user_permissions($id);

    return $rtn ?
        $self->error($rtn) : # redirect after db edit:
            $self->redirect( $self->query->url . '/admin/user/default/'.$id );
}

#-------------------------------------------------------------------------------
sub update_user_permissions : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);

    my $user_id = $self->param('id')
	|| return $self->error('no id passed to '.$self->get_current_runmode);

    my @function_ids = $self->query->param('function_id'); # $self->debug(\@function_ids);

    my %args = (
        function_ids => \@function_ids,
        user_id      => $user_id,
    );

    my $rtn = $self->model('User')->update_user_permissions(\%args);

    return $rtn  ?
        $self->error($rtn) :
            $self->redirect( $self->query->url . '/admin/user/default/'.$user_id );
}

#-------------------------------------------------------------------------------
sub delete_user : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);

    my $user_id = $self->param('id')
	|| return $self->error('no id passed to '.$self->get_current_runmode);

    my $user = $self->model('User')->get_user_profile($user_id);

    $self->tt_params( user => $user );

    # need confirmation before deleting user:
    return $self->tt_process('admin/user/delete_user.tt')
        unless $self->query->param('confirm_reset');

    my $rtn = $self->model('User')->delete_user($user_id);

    return $rtn ?
        $self->error($rtn) : # redirect after db edit:
            $self->redirect( $self->query->url . '/admin/user' );
}

#-------------------------------------------------------------------------------

# returns hashref of selected_user (users details), permissions_type
# (custom/default), user_permissions (list)
sub _get_user_details {
    my $self    = shift; $self->_debug_path('_get_user_details');
    my $user_id = shift;

    my %data;

    my $this_user = $data{selected_user}
		= $self->model('User')->get_user_profile($user_id); # hashref

    # load custom user permissions (if any):
    my $this_user_permissions
		= $self->model('User')->get_user_permissions($user_id); # arrayref

    # flag for template (if permissions set here - it's custom):
    $data{permissions_type} = @$this_user_permissions ? 'custom' : 'default';

    # if no user_permissions, load default settings for this users' group:
    if (! @$this_user_permissions) {
        $this_user_permissions
			= $self->model('User')->get_user_group_functions($this_user->group_id);
    }

    # get user_permissions, with active => 1 if function.id also in user_group_functions table:
    $data{user_permissions} = $self->get_user_functions($this_user_permissions); # in LIMS::Admin::Controller

    return \%data;
}

1;