#!/usr/bin/perl
#
# Generates members of a mailing list for sympa
#
use strict;
use warnings;
use perunServicesInit;
use perunServicesUtils;
use Text::Unidecode;
use POSIX qw/strftime/;

local $::SERVICE_NAME = "sympa";
local $::PROTOCOL_VERSION = "3.0.0";
my $SCRIPT_VERSION = "3.0.2";

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

#Constants
our $A_USER_NAME;                        *A_USER_NAME =                       \'urn:perun:user:attribute-def:core:displayName';
our $A_USER_MAIL;                        *A_USER_MAIL =                       \'urn:perun:user:attribute-def:def:preferredMail';
our $A_USER_LANG;                        *A_USER_LANG =                       \'urn:perun:user:attribute-def:def:preferredLanguage';
our $A_USER_STATUS;                      *A_USER_STATUS =                     \'urn:perun:member:attribute-def:core:status';
our $A_USER_OPT_OUT;                     *A_USER_OPT_OUT =                    \'urn:perun:member_resource:attribute-def:def:optOutMailingList';

our $A_RESOURCE_MAILING_LIST_NAME;           *A_RESOURCE_MAILING_LIST_NAME =            \'urn:perun:resource:attribute-def:def:mailingListName';
our $A_RESOURCE_MAILING_LIST_VARIANTS;       *A_RESOURCE_MAILING_LIST_VARIANTS =        \'urn:perun:resource:attribute-def:def:mailingListUsesLangVariants'; # true for -cs and -en variants
our $A_RESOURCE_MAILING_LIST_NONVALID_USERS; *A_RESOURCE_MAILING_LIST_NONVALID_USERS =  \'urn:perun:resource:attribute-def:def:mailingListAllowInvalidUsers'; # true to allow users with status other than VALID
our $A_RESOURCE_DISABLE_OPT_OUT;             *A_RESOURCE_DISABLE_OPT_OUT =              \'urn:perun:resource:attribute-def:def:disableMailingListOptOut';


my $mailinglistStruc = {};  # $mailinglistStruc->{"mailing list name"}->{"user's e-mail"}->{"user's name"}

my $mailinglistsDirectory = "$DIRECTORY/mailinglists";
mkdir $mailinglistsDirectory or die "Can't mkdir $mailinglistsDirectory: $!";


foreach my $resourceId ($data->getResourceIds()) {

	my $listVariantsAttribute = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_RESOURCE_MAILING_LIST_VARIANTS);
	my $nonValidUsersAttribute = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_RESOURCE_MAILING_LIST_NONVALID_USERS);
	my $disableOptOutAttribute = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_RESOURCE_DISABLE_OPT_OUT);
	my $listNameAttribute = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_RESOURCE_MAILING_LIST_NAME);

	my $useLangVariants = (defined($listVariantsAttribute) && ($listVariantsAttribute eq "true") );
	my $allowNonvalidUsers = (defined($nonValidUsersAttribute) && ($nonValidUsersAttribute eq "true") );
	my $disableOptOut = (defined($disableOptOutAttribute) && ($disableOptOutAttribute eq "true") );

	my $fullListName = "$listNameAttribute";
	my $listName = $fullListName;
	my $listDomain = "";

	# check if list name contains also domain
	my $index = index($fullListName, '@');
	if ($index ne -1) {
		# split name to append correct lang variant
		$listName = substr($fullListName, 0, $index);
		$listDomain = substr($fullListName, $index);
	}

	my $listNameEN = $listName . "-en" . $listDomain;
	my $listNameCS = $listName . "-cs" . $listDomain;

	#create not existing mailing list in structure (even if is empty)
	if($useLangVariants) {
		$mailinglistStruc->{$listNameEN} = {} unless $mailinglistStruc->{$listNameEN};
		$mailinglistStruc->{$listNameCS} = {} unless $mailinglistStruc->{$listNameCS};
	} else {
		$mailinglistStruc->{$fullListName} = {} unless $mailinglistStruc->{$fullListName};
	}

	foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) {

		my $memberStatus = $data->getMemberAttributeValue(member => $memberId, attrName => $A_USER_STATUS);
		my $userOptOut = $data->getMemberResourceAttributeValue(resource => $resourceId, member => $memberId, attrName => $A_USER_OPT_OUT);
		my $userLang = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_LANG);
		my $userMail = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_MAIL);
		my $userName = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_NAME);

		#list only VALID members except if allowNonvalidUsers is true
		next unless(($memberStatus eq "VALID") || ($allowNonvalidUsers));

		# check if mailing list respect opt-out
		unless ($disableOptOut) {
			# list only members that did not opt out
			next if defined $userOptOut;
		}

		my $listNameWithLang = $fullListName;
		if($useLangVariants) {
			if(defined($userLang) && $userLang eq "cs") {
				$listNameWithLang = $listNameCS;
			} else {
				$listNameWithLang = $listNameEN;
			}
		}

		$mailinglistStruc->{$listNameWithLang}->{$userMail}->{$A_USER_NAME} = $userName;
	}

}


for my $listName (keys %$mailinglistStruc) {
    my $fileName = "$mailinglistsDirectory/$listName";
    open FILE,">$fileName" or die "Cannot open $fileName: $! \n";

    for my $mail (sort keys %{$mailinglistStruc->{$listName}}) {
		print FILE $mail, " ", unidecode($mailinglistStruc->{$listName}->{$mail}->{$A_USER_NAME}), "\n";
    }

    close FILE or die $!;
}

perunServicesInit::finalize;
