#!/usr/bin/perl
use feature "switch";
use strict;
use warnings;
use perunServicesInit;
use perunServicesUtils;

local $::SERVICE_NAME = "ad_user_vsup_service";
local $::PROTOCOL_VERSION = "3.0.1";
my $SCRIPT_VERSION = "3.0.6";

perunServicesInit::init;
my $DIRECTORY = perunServicesInit::getDirectory;
my $fileName = "$DIRECTORY/$::SERVICE_NAME".".ldif";
my $baseDnFileName = "$DIRECTORY/baseDN";
my $topDnFileName = "$DIRECTORY/topDN";

my $data = perunServicesInit::getHashedHierarchicalData;

#Constants
our $A_F_BASE_DN;  *A_F_BASE_DN = \'urn:perun:facility:attribute-def:def:adServiceBaseDN';
our $A_F_DOMAIN;  *A_F_DOMAIN = \'urn:perun:facility:attribute-def:def:adDomain';
our $A_F_UAC;  *A_F_UAC = \'urn:perun:facility:attribute-def:def:adServiceUAC';
our $A_FIRST_NAME;  *A_FIRST_NAME = \'urn:perun:user:attribute-def:core:firstName';
our $A_LAST_NAME;  *A_LAST_NAME = \'urn:perun:user:attribute-def:core:lastName';
our $A_ARTISTIC_FIRST_NAME; *A_ARTISTIC_FIRST_NAME = \'urn:perun:user:attribute-def:def:artisticFirstName';
our $A_ARTISTIC_LAST_NAME; *A_ARTISTIC_LAST_NAME = \'urn:perun:user:attribute-def:def:artisticLastName';
our $A_LOGIN; *A_LOGIN = \'urn:perun:user_facility:attribute-def:virt:login';
our $A_BLACKLISTED;  *A_BLACKLISTED = \'urn:perun:user_facility:attribute-def:virt:blacklisted';
our $A_IS_SERVICE; *A_IS_SERVICE = \'urn:perun:user:attribute-def:core:serviceUser';
our $A_UCO; *A_UCO= \'urn:perun:user:attribute-def:def:ucoVsup';
our $A_TITLE_BEFORE;  *A_TITLE_BEFORE = \'urn:perun:user:attribute-def:core:titleBefore';
our $A_TITLE_AFTER;  *A_TITLE_AFTER = \'urn:perun:user:attribute-def:core:titleAfter';
our $A_PHONE;  *A_PHONE = \'urn:perun:user:attribute-def:def:phoneDc2';
our $A_CARD_BARCODES;  *A_CARD_BARCODES = \'urn:perun:user:attribute-def:def:cardBarCodes';
our $A_CARD_CHIP_NUMBERS;  *A_CARD_CHIP_NUMBERS = \'urn:perun:user:attribute-def:def:cardCodes';
our $A_VSUP_PREF_MAIL;  *A_VSUP_PREF_MAIL = \'urn:perun:user:attribute-def:def:vsupPreferredMail';
our $A_VSUP_SSH_KEYS;  *A_VSUP_SSH_KEYS = \'urn:perun:user:attribute-def:def:sshPublicKey';
our $A_VSUP_EXCHANGE_MAIL_ALIASES;  *A_VSUP_EXCHANGE_MAIL_ALIASES = \'urn:perun:user:attribute-def:def:vsupExchangeMailAliases';
our $A_AD_DISPLAY_NAME;  *A_AD_DISPLAY_NAME = \'urn:perun:user:attribute-def:def:adDisplayName';

# CHECK ON FACILITY ATTRIBUTES
if (!defined($data->getFacilityAttributeValue( attrName => $A_F_BASE_DN ))) {
	exit 1;
}
if (!defined($data->getFacilityAttributeValue( attrName => $A_F_DOMAIN ))) {
	exit 1;
}
if (!defined($data->getFacilityAttributeValue( attrName => $A_F_UAC ))) {
	exit 1;
}

my $baseDN = $data->getFacilityAttributeValue( attrName => $A_F_BASE_DN );
my $domain = $data->getFacilityAttributeValue( attrName => $A_F_DOMAIN );
my $uac = $data->getFacilityAttributeValue( attrName => $A_F_UAC );

# GATHER USERS
my $users;  # $users->{$login}->{ATTR} = $attrValue;

#
# PRINT BASE_DN FILE
#
open FILE,">:encoding(UTF-8)","$baseDnFileName" or die "Cannot open $baseDnFileName: $! \n";
print FILE $baseDN;
close(FILE);

#
# PRINT TOP_DN FILE
#
open FILE,">:encoding(UTF-8)","$topDnFileName" or die "Cannot open $topDnFileName: $! \n";
$baseDN =~ m/(DC=(.*))/;
print FILE $1;
close(FILE);

#
# AGGREGATE DATA
#
# FOR EACH USER
foreach my $memberId ($data->getMemberIdsForFacility()) {

	my $blacklisted = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_BLACKLISTED );

	if (defined $blacklisted and ($blacklisted == 1)) {
		# skip blacklisted users !security ban!
		next;
	}

	my $serviceUser = $data->getUserAttributeValue( member => $memberId, attrName => $A_IS_SERVICE );

	# Print only service user accounts
	if (defined $serviceUser and ($serviceUser == 1)) {

		my $login = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_LOGIN );
		my $artisticFirstName = $data->getUserAttributeValue( member => $memberId, attrName => $A_ARTISTIC_FIRST_NAME );
		my $firstName = $data->getUserAttributeValue( member => $memberId, attrName => $A_FIRST_NAME );
		my $artisticLastName = $data->getUserAttributeValue( member => $memberId, attrName => $A_ARTISTIC_LAST_NAME );
		my $lastName = $data->getUserAttributeValue( member => $memberId, attrName => $A_LAST_NAME );

		$users->{$login}->{"DN"} = "CN=" . $login . "," . $baseDN;
		# store standard attrs
		$users->{$login}->{$A_FIRST_NAME} = $artisticFirstName || $firstName;
		$users->{$login}->{$A_LAST_NAME} = $artisticLastName || $lastName;
		$users->{$login}->{$A_AD_DISPLAY_NAME} = $data->getUserAttributeValue( member => $memberId, attrName => $A_AD_DISPLAY_NAME );
		$users->{$login}->{$A_UCO} = $data->getUserAttributeValue( member => $memberId, attrName => $A_UCO );
		$users->{$login}->{$A_TITLE_BEFORE} = $data->getUserAttributeValue( member => $memberId, attrName => $A_TITLE_BEFORE );
		$users->{$login}->{$A_TITLE_AFTER} = $data->getUserAttributeValue( member => $memberId, attrName => $A_TITLE_AFTER );
		$users->{$login}->{$A_PHONE} = $data->getUserAttributeValue( member => $memberId, attrName => $A_PHONE );
		$users->{$login}->{$A_CARD_BARCODES} = $data->getUserAttributeValue( member => $memberId, attrName => $A_CARD_BARCODES );
		$users->{$login}->{$A_CARD_CHIP_NUMBERS} = $data->getUserAttributeValue( member => $memberId, attrName => $A_CARD_CHIP_NUMBERS );
		$users->{$login}->{$A_VSUP_PREF_MAIL} = $data->getUserAttributeValue( member => $memberId, attrName => $A_VSUP_PREF_MAIL );
		$users->{$login}->{$A_VSUP_SSH_KEYS} = $data->getUserAttributeValue( member => $memberId, attrName => $A_VSUP_SSH_KEYS );
		$users->{$login}->{$A_VSUP_EXCHANGE_MAIL_ALIASES} = $data->getUserAttributeValue( member => $memberId, attrName => $A_VSUP_EXCHANGE_MAIL_ALIASES );

	}

}

#
# PRINT user data LDIF
#
open FILE,">$fileName" or die "Cannot open $fileName: $! \n";
binmode FILE, ":utf8";

# FOR EACH USER ON FACILITY
my @logins = sort keys %{$users};
for my $login (@logins) {

	# print attributes, which are never empty
	print FILE "dn: " . $users->{$login}->{"DN"} . "\n";

	print FILE "cn: " . $login . "\n";
	print FILE "samAccountName: " . $login . "\n";
	print FILE "userPrincipalName: " . $login . "\@umprum.cz" . "\n";
	# enable accounts (if not) using service propagation
	print FILE "userAccountControl: " . $uac . "\n";

	# skip attributes which are empty and LDAP can't handle it (FIRST_NAME, EMAIL)
	my $sn = $users->{$login}->{$A_LAST_NAME};
	my $givenName = $users->{$login}->{$A_FIRST_NAME};
	my $adDisplayName = $users->{$login}->{$A_AD_DISPLAY_NAME};
	my $uco = $users->{$login}->{$A_UCO};
	my $titleBefore = $users->{$login}->{$A_TITLE_BEFORE};
	my $titleAfter = $users->{$login}->{$A_TITLE_AFTER};
	my $phone = $users->{$login}->{$A_PHONE};
	my $barcodes = $users->{$login}->{$A_CARD_BARCODES};
	my $chipNumbers = $users->{$login}->{$A_CARD_CHIP_NUMBERS};
	my $vsupPrefMail = $users->{$login}->{$A_VSUP_PREF_MAIL};
	my $sshKeys = $users->{$login}->{$A_VSUP_SSH_KEYS};
	my $exchangeMailAliases = $users->{$login}->{$A_VSUP_EXCHANGE_MAIL_ALIASES};

	# print display name from firstName/lastName only
	my $printedDisplayName = undef;
	if (defined $givenName and length $givenName and defined $sn and length $sn) {
		$printedDisplayName = $givenName . " " . $sn;
	} elsif (defined $givenName and length $givenName and !(defined $sn and length $sn)) {
		$printedDisplayName = $givenName;
	} elsif (!(defined $givenName and length $givenName) and defined $sn and length $sn) {
		$printedDisplayName = $sn;
	}
	# prefer manually set display name for service accounts if present
	if (defined $adDisplayName and length $adDisplayName) {
		$printedDisplayName = $adDisplayName;
	}
	if (defined $printedDisplayName and length $printedDisplayName) {
		print FILE "displayName: " . $printedDisplayName . "\n";
		print FILE "gecos: " . $printedDisplayName . "\n";
	}

	if (defined $sn and length $sn) {
		print FILE "sn: " . $sn . "\n";
	}
	if (defined $givenName and length $givenName) {
		print FILE "givenName: " . $givenName . "\n";
	}

	if (defined $vsupPrefMail and length $vsupPrefMail) {
		print FILE "mail: " . $vsupPrefMail . "\n";
	} else {
		print FILE "mail: " . $login . "\@" . $domain . "\n";
	}

	if (defined $uco and length $uco) {
		print FILE "vsupPersonPersonalId: " . $uco . "\n";
	}

	if (defined $titleBefore and length $titleBefore) {
		print FILE "vsupPersonTitleHead: " . $titleBefore . "\n";
	}

	if (defined $titleAfter and length $titleAfter) {
		print FILE "vsupPersonTitleTail: " . $titleAfter . "\n";
	}

	if (defined $phone and length $phone) {
		print FILE "telephoneNumber: " . $phone . "\n";
	}

	foreach my $val (@$barcodes) {
		print FILE "vsupPersonIdCardBarcode: " . $val . "\n";
	}

	foreach my $val (@$chipNumbers) {
		print FILE "vsupPersonIdCardChipNumber: " . $val . "\n";
	}

	foreach my $val (@$sshKeys) {
		print FILE "altSecurityIdentities: " . $val . "\n";
	}

	# preferred mail must be in proxyAddresses as primary mail for service users
	if (defined $vsupPrefMail and length $vsupPrefMail) {
		print FILE "proxyAddresses: SMTP:" . $vsupPrefMail . "\n";
	}
	foreach my $val (@$exchangeMailAliases) {
		print FILE "proxyAddresses: smtp:" . $val . "\n";
	}

	# print classes
	print FILE "objectclass: top\n";
	print FILE "objectclass: person\n";
	print FILE "objectclass: user\n";
	print FILE "objectclass: organizationalPerson\n";

	# There MUST be an empty line after each entry, so entry sorting and diff works on slave part
	print FILE "\n";

}

close(FILE);

perunServicesInit::finalize;
