#!/usr/bin/perl

use strict;
use warnings;
use perunServicesInit;
use perunServicesUtils;
use Text::Unidecode;

our $SERVICE_NAME = "passwd_scp";
our $PROTOCOL_VERSION = "3.0.1";
my $SCRIPT_VERSION = "3.1.1";

perunServicesInit::init;
my $DIRECTORY = perunServicesInit::getDirectory;
my $data = perunServicesInit::getHashedHierarchicalData;

#Constants
our $A_FACILITY_MIN_UID;                       *A_FACILITY_MIN_UID =                      \'urn:perun:facility:attribute-def:virt:minUID';
our $A_FACILITY_MAX_UID;                       *A_FACILITY_MAX_UID =                      \'urn:perun:facility:attribute-def:virt:maxUID';
our $A_FACILITY_DESTINATION_FILE;              *A_FACILITY_DESTINATION_FILE =             \'urn:perun:facility:attribute-def:def:passwdScpDestinationFile';
our $A_USER_FACILITY_LOGIN;                    *A_USER_FACILITY_LOGIN =                   \'urn:perun:user_facility:attribute-def:virt:login';
our $A_USER_FACILITY_UID;                      *A_USER_FACILITY_UID =                     \'urn:perun:user_facility:attribute-def:virt:UID';
our $A_USER_FACILITY_GID;                      *A_USER_FACILITY_GID =                     \'urn:perun:user_facility:attribute-def:virt:defaultUnixGID';
our $A_USER_FACILITY_SHELL;                    *A_USER_FACILITY_SHELL =                   \'urn:perun:user_facility:attribute-def:def:shell_passwd-scp';
our $A_USER_FIRST_NAME;                        *A_USER_FIRST_NAME =                       \'urn:perun:user:attribute-def:core:firstName';
our $A_USER_LAST_NAME;                         *A_USER_LAST_NAME =                        \'urn:perun:user:attribute-def:core:lastName';
our $A_USER_FACILITY_HOME_MOUNT_POINT;         *A_USER_FACILITY_HOME_MOUNT_POINT =        \'urn:perun:user_facility:attribute-def:def:homeMountPoint';

my $passwd_file_name = "$DIRECTORY/$::SERVICE_NAME";
my $passwd_file_destination_file_name = "$DIRECTORY/$::SERVICE_NAME" . "_destination";
my $min_uid_file_name = "$DIRECTORY/min_uid";
my $max_uid_file_name = "$DIRECTORY/max_uid";

###### min_uid and max_uid file #####
open MIN_UID,">$min_uid_file_name" or die "Cannot open $min_uid_file_name: $! \n";
open MAX_UID,">$max_uid_file_name" or die "Cannot open $max_uid_file_name: $! \n";
print MIN_UID $data->getFacilityAttributeValue(attrName => $A_FACILITY_MIN_UID), "\n";
print MAX_UID $data->getFacilityAttributeValue(attrName => $A_FACILITY_MAX_UID), "\n";
close MIN_UID;
close MAX_UID;
#####################################
open DESTINATION,">$passwd_file_destination_file_name" or die "Cannot open $passwd_file_destination_file_name: $! \n";
print DESTINATION $data->getFacilityAttributeValue(attrName => $A_FACILITY_DESTINATION_FILE), "\n";
close DESTINATION;

####### passswd and shadow file ######################
open PASSWD,">$passwd_file_name" or die "Cannot open $passwd_file_name: $! \n";


#hash memberAttributesByLogin to eliminate duplicities
#logins contain a reference to a hash of the attributes used to print files, e.g.:
#$memberAttributesByLogin->{$login}->{$A_USER_FACILITY_UID} = $uid;
my $memberAttributesByLogin = {};
foreach my $resourceId ($data->getResourceIds()) {
	my %values;
	foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) {
		my $login = $data->getUserFacilityAttributeValue(attrName => $A_USER_FACILITY_LOGIN, member => $memberId);
		unless(exists $memberAttributesByLogin->{$login}) {
			$memberAttributesByLogin->{$login} = {};
			$memberAttributesByLogin->{$login}->{$A_USER_FACILITY_LOGIN} = $login;
			$memberAttributesByLogin->{$login}->{$A_USER_FACILITY_UID} = $data->getUserFacilityAttributeValue(attrName => $A_USER_FACILITY_UID, member => $memberId);
			$memberAttributesByLogin->{$login}->{$A_USER_FACILITY_GID} = $data->getUserFacilityAttributeValue(attrName => $A_USER_FACILITY_GID, member => $memberId);
			$memberAttributesByLogin->{$login}->{$A_USER_FIRST_NAME} = $data->getUserAttributeValue(attrName => $A_USER_FIRST_NAME, member => $memberId);
			$memberAttributesByLogin->{$login}->{$A_USER_LAST_NAME} = $data->getUserAttributeValue(attrName => $A_USER_LAST_NAME, member => $memberId);
			$memberAttributesByLogin->{$login}->{$A_USER_FACILITY_HOME_MOUNT_POINT} = $data->getUserFacilityAttributeValue(attrName => $A_USER_FACILITY_HOME_MOUNT_POINT, member => $memberId);
			$memberAttributesByLogin->{$login}->{$A_USER_FACILITY_SHELL} = $data->getUserFacilityAttributeValue(attrName => $A_USER_FACILITY_SHELL, member => $memberId);
		}
	}
}
#print data to files
#case-insensitive sort of logins
for my $login (sort {"\U$a" cmp "\U$b"} keys %$memberAttributesByLogin) {
	my %memberAttributes = %{$memberAttributesByLogin->{$login}};
	$memberAttributes{$A_USER_FACILITY_HOME_MOUNT_POINT} =~ s#^.*/\./#/#;

	print PASSWD $memberAttributes{$A_USER_FACILITY_LOGIN}.":x:";
	print PASSWD $memberAttributes{$A_USER_FACILITY_UID}.":";
	print PASSWD $memberAttributes{$A_USER_FACILITY_GID}.":";

	my $userName = "";
	if($memberAttributes{$A_USER_FIRST_NAME}) {
		$userName = $memberAttributes{$A_USER_FIRST_NAME};
		$userName.= " " . $memberAttributes{$A_USER_LAST_NAME} if $memberAttributes{$A_USER_LAST_NAME};
	} else {
		$userName.= $memberAttributes{$A_USER_LAST_NAME} if $memberAttributes{$A_USER_LAST_NAME};
	}

	print PASSWD unidecode($userName) . ":";
	print PASSWD $memberAttributes{$A_USER_FACILITY_HOME_MOUNT_POINT}."/".$memberAttributes{$A_USER_FACILITY_LOGIN}.":";

	print PASSWD $memberAttributes{$A_USER_FACILITY_SHELL};
	print PASSWD "\n";
}

close(PASSWD);
#####################################################
perunServicesInit::finalize;
