###
### Script pro plneni alias tabulek z WSDL souboru pro Postfix
###


use strict;
use warnings;
use Data::Dumper;
use Config::Simple;
use Log::Log4perl qw(get_logger :levels);
use XML::LibXML;

# metody : getAliases getOrgMailboxes getGroups
# Logování debug info warn error fatal

# Konfigurační soubor
my $config = new Config::Simple('generate_file.conf');
# Logování
Log::Log4perl::init('generate_file.conf');
# stupen logování
Log::Log4perl->easy_init($WARN);
# instance loggeru
my $logger = Log::Log4perl->get_logger();

# delete and create directory for output files if not exists tmp_dir and tmp_dir_groups
my $tmp_dir = $config->param('tmp_dir');
my $tmp_dir_groups = $config->param('tmp_dir_groups_vsb_cz');
my $valid_dir = $config->param('valid_dir');
my $valid_dir_groups = $config->param('valid_dir_groups_vsb_cz');

if (-d $tmp_dir) {
    system("rm -rf $tmp_dir");
    $logger->info("Directory $tmp_dir deleted");
}
if (-d $tmp_dir_groups) {
    system("rm -rf $tmp_dir_groups");
    $logger->info("Directory $tmp_dir_groups deleted");
}
if (!-d $tmp_dir) {
    mkdir $tmp_dir or die "Failed to create directory: $tmp_dir";
    $logger->info("Directory $tmp_dir created");
}
if (!-d $tmp_dir_groups) {
    mkdir $tmp_dir_groups or die "Failed to create directory: $tmp_dir_groups";
    $logger->info("Directory $tmp_dir_groups created");
}




### MAIN ###

## uz ok
my $getgroups = getData('getGroups');
parse_xml_groups($getgroups);

# uz ok
my $getOrgMailboxes = getData('getOrgMailboxes');
parse_xml_orgMailboxes($getOrgMailboxes);

# uz ok
my $getaliases = getData('getAliases');
parse_xml_aliases($getaliases);

# vytvoreni tuo z vsb
recipient_vsb_to_tuo();

# kopirovani do valid umísteni
my $rsync_command = "rsync -avxp $tmp_dir/ $valid_dir/ > /dev/null 2>&1";
system($rsync_command) == 0 or $logger->error("Error: $rsync_command");

# postmap virtual, canonical, recipient_access
my $postmap_command = "postmap $valid_dir/virtual_vsb_cz && postmap $valid_dir/virtual_orgMailboxes_vsb_cz && postmap $valid_dir/canonical_vsb_cz && postmap $valid_dir/canonical_orgMailboxes_vsb_cz && postmap $valid_dir/recipient_access_vsb_cz";
system($postmap_command) == 0 or $logger->error("Error: $postmap_command");
# groups_vsb_cz virtual aliases recipient_access
my $postmap_command_groups = "postmap $valid_dir_groups/virtual_vsb_cz && postmap $valid_dir_groups/aliases_vsb_cz && postmap $valid_dir_groups/recipient_access_vsb_cz";
system($postmap_command_groups) == 0 or $logger->error("Error: $postmap_command_groups");





### SUBS ###

sub cut_domain {
    my $email = shift;
    # cut domain from email
    $email =~ s/@.*//;
    return $email;
}

############################################

sub recipient_vsb_to_tuo {

    my $filename = $tmp_dir . '/' . "recipient_access_vsb_cz";
    open(my $fh, '<:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";
    #replace vsb.cz to tuo.cz
    my $filename2 = $tmp_dir . '/' . "recipient_access_tuo_cz";
    open(my $fh2, '>>:encoding(UTF-8)', $filename2) or die "Could not open file '$filename2' $!";
    while (my $row = <$fh>) {
        chomp $row;
        my $row2 = $row;
        $row =~ s/vsb.cz/tuo.cz/;
        print $fh2 $row ."\n";
    }
    close $fh;
    close $fh2;
}

############################################

sub parse_xml_aliases {
my $data = shift;
# print Dumper($data);

# my $rescp_string;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($data);
my $root = $doc->getDocumentElement;
my @account = $root->findnodes('//account');

foreach my $mailbox (@account) {
    my $rescp_string = "";
    my $login = $mailbox->findvalue('login');
    my $mainAlias = $mailbox->findvalue('mainAlias');
    my $mainAliasCut = cut_domain($mainAlias);
    my @alias_group = $mailbox->findnodes('aliases/alias');
    my @servers = $mailbox->findnodes('servers/server');
    my @phone = $mailbox->findnodes('phones/phone');
    my @copy = $mailbox->findnodes('copies/copy');
    if (@copy != 0 || @phone != 0) {
        my @mergecp = (@copy, @phone);
        my @rescp = map { $_->textContent } @mergecp;
        $rescp_string = join(",", @rescp);
    }

    # virtual_vsb_cz 
    my $filename = $tmp_dir . '/' . "virtual_vsb_cz";
    open(my $fh, '>>:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";
    my @server = map { $_->textContent } @servers;
    my @aliases = map { $_->textContent } @alias_group;

    foreach my $srv (@server) {
        print $fh $mainAlias ."\t\t". $login ."\@vsb.cz\n";
        print $fh $login ."\@vsb.cz\t\t". $login ."@". $srv;
        if ($rescp_string) {
            print $fh ",". $rescp_string;
        }
        print $fh "\n";
    }
    if (@aliases) {
    foreach my $alias (@aliases) {
        print $fh $alias ."\t\t". $login ."\@vsb.cz\n";
        }
    }
    close $fh;
    $logger->info("File $filename created");

    # canonical_vsb_cz 
    my $filename2 = $tmp_dir . '/' . "canonical_vsb_cz";
    open(my $fh2, '>>:encoding(UTF-8)', $filename2) or die "Could not open file '$filename2' $!";
    print $fh2  "/^". $login ."\@(.+\\.|)vsb\\.cz\$\/\t\t".$mainAlias."\n";
    close $fh2;
    $logger->info("File $filename2 created");

    # recipient_access_vsb_cz 
    my $filename3 = $tmp_dir . '/' . "recipient_access_vsb_cz";
    open(my $fh3, '>>:encoding(UTF-8)', $filename3) or die "Could not open file '$filename3' $!";
    print $fh3 $mainAlias ."\t\tOK\n";
    if (@aliases) {
        foreach my $alias (@aliases) {
            print $fh3 $alias ."\t\tOK\n";
        }
    }
    print $fh3 $login ."\@vsb.cz\t\tOK\n";
    close $fh3;
    $logger->info("File $filename3 created");
}

}   


############################################


sub parse_xml_orgMailboxes {

my $data = shift;
#  print Dumper($data);
my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($data);
my $root = $doc->getDocumentElement;
my @orgmailbox = $root->findnodes('//orgMailbox');

foreach my $mailbox (@orgmailbox) {
    my $login = $mailbox->findvalue('login');
    my $mainAlias = $mailbox->findvalue('mainAlias');
    my @alias_group = $mailbox->findnodes('aliases/alias');
    # my $alias_group = $mailbox->findvalue('aliases');
    my @servers = $mailbox->findnodes('servers/server');
    my $mainAliasCut = cut_domain($mainAlias);
    # print "Group: $login\n";
    # print "Main alias: $mainAlias\n";
    # print "Server: $servers\n";

    # virtual_orgMailboxes 
    my $filename = $tmp_dir . '/' . "virtual_orgMailboxes_vsb_cz";
    open(my $fh, '>>:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";
    my @server = map { $_->textContent } @servers;
    foreach my $srv (@server) {
        print $fh $mainAlias ."\t\t". $login ."\@vsb.cz\n";
        print $fh $login ."\@vsb.cz\t\t". $login ."@". $srv ."\n";
        if (@alias_group) {
            my @aliases = map { $_->textContent } @alias_group;
            foreach my $alias (@aliases) {
                print $fh $alias ."\t\t". $login ."\@vsb.cz\n";
            }
        }
    }
    close $fh;
    $logger->info("File $filename created");

    # canonical_orgMailboxes_vsb_cz 
    my $filename2 = $tmp_dir . '/' . "canonical_orgMailboxes_vsb_cz";
    open(my $fh2, '>>:encoding(UTF-8)', $filename2) or die "Could not open file '$filename2' $!";
    print $fh2  "/^". $login ."\@(.+\\.|)vsb\\.cz\$\/\t\t".$mainAlias."\n";
    close $fh2;
    $logger->info("File $filename2 created");

    # recipient_access_orgMailboxes_vsb_cz 
    my $filename3 = $tmp_dir . '/' . "recipient_access_vsb_cz";
    open(my $fh3, '>>:encoding(UTF-8)', $filename3) or die "Could not open file '$filename3' $!";
    print $fh3 $mainAlias ."\t\tOK\n";
    if (@alias_group) {
        my @aliases = map { $_->textContent } @alias_group;
        foreach my $alias (@aliases) {
            print $fh3 $alias ."\t\tOK\n";
        }
    }
    close $fh3;
    $logger->info("File $filename3 created");

}
}    

############################################

sub parse_xml_groups {


my $data = shift;
    # print Dumper($data);
my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($data);
my $root = $doc->getDocumentElement;
my @groups = $root->findnodes('//group');
my $restricted_group = $config->param('restricted_group');

foreach my $group (@groups) {
    my $name = $group->findvalue('name');
    my $mainAlias = $group->findvalue('mainAlias');
    my @alias_group = $group->findnodes('aliases/alias');
    # my $alias_groupCut = cut_domain($alias_group);
    my $mainAliasCut = cut_domain($mainAlias);
    my $internal = $group->findvalue('internal');
    my @members = $group->findnodes('members/member');
    my @extMembers = $group->findnodes('extMembers/extMember');
    # print "Group: $name\n";
    # print "Main alias: $mainAlias\n";
    # print "Members: ";
    # foreach my $member (@members) {
    #     print $member->textContent . " ";
    # }
    # print "\nextMembers: ";
    # foreach my $member (@extMembers) {
    #     print $member->textContent . " ";
    # }
    # print "\n";

    # print groups file with members
    my $filename = $tmp_dir_groups . '/' . $mainAliasCut;
    open(my $fh, '>:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";
    foreach my $member (@members) {
        print $fh $member->textContent . "\@vsb.cz\n";
    }
    foreach my $member (@extMembers) {
        print $fh $member->textContent . "\n";
    }
    close $fh;
    $logger->info("File $filename created");

    # groups/aliases_vsb_cz 
    my $galiases = $tmp_dir_groups . '/' . 'aliases_vsb_cz';
    open(my $fh2, '>>:encoding(UTF-8)', $galiases) or die "Could not open file '$galiases' $!";
    if (grep {$_ eq $mainAliasCut} split /,/, $restricted_group) {
        print $fh2 $mainAliasCut ."\t\t\"|sudo /etc/scripts/posta/rest_send.pl $valid_dir_groups/". $mainAliasCut ."\"\n";
    } else {
    print $fh2 $mainAliasCut ."\t\t:include:$valid_dir_groups/". $mainAliasCut ."\n";
    if (@alias_group) {
        my @aliases = map { $_->textContent } @alias_group;
        foreach my $alias (@aliases) {
            $alias = cut_domain($alias);
            print $fh2 $alias ."\t\t:include:$valid_dir_groups/". $mainAliasCut ."\n";
        }
    }
    }

    close $fh2;
    $logger->info("File $galiases created");

    # restriction all user recipient_access_vsb_cz 
    my $rest_all = $tmp_dir . '/' . 'recipient_access_vsb_cz';
    open(my $fh4, '>>:encoding(UTF-8)', $rest_all) or die "Could not open file '$rest_all' $!";
    if ($internal ne "true"){
        print $fh4 $mainAlias ."\t\tOK\n";
        if (@alias_group) {
            # parse by @vsb.cz
            my @aliases = map { $_->textContent } @alias_group;
            foreach my $alias (@aliases) {
                print $fh4 $alias ."\t\tOK\n";
            }
        }
    }
    close $fh4;
    $logger->info("File $galiases created");

    # groups/virtual_vsb_cz 
    my $gvirtual = $tmp_dir_groups . '/' . 'virtual_vsb_cz';
    open(my $fh3, '>>:encoding(UTF-8)', $gvirtual) or die "Could not open file '$gvirtual' $!";
    print $fh3 $mainAlias ."\t\t". $mainAliasCut ."\@localhost.vsb.cz\n";
    if (@alias_group) {
        my @aliases = map { $_->textContent } @alias_group;
        foreach my $alias (@aliases) {
            
            print $fh3 $alias ."\t\t". $mainAliasCut ."\@localhost.vsb.cz\n";
        }
    }
    close $fh3;
    $logger->info("File $gvirtual created");

    # groups/recipient_access_vsb_cz 
    my $recipient = $tmp_dir_groups . '/' . 'recipient_access_vsb_cz';  
    open(my $fh5, '>>:encoding(UTF-8)', $recipient) or die "Could not open file '$recipient' $!";
    if ($internal eq "true") {
        print $fh5 "/^". $mainAliasCut ."\@.*vsb.cz\$\/\t\tvsb_cz_only\n";
        if (@alias_group) {
            my @aliases = map { $_->textContent } @alias_group;
            foreach my $alias (@aliases) {
                $alias = cut_domain($alias);
                print $fh5 "/^". $alias ."\@.*vsb.cz\$\/\t\tvsb_cz_only\n";
            }
        }
    }
    close $fh5;
    $logger->info("File $recipient created");

}
}  

############################################

sub getData {
    my $myget = shift;
    my $soapaction = $config->param('soapaction');
    my $endpoint = $config->param('endpoint');
    my $namespace = $config->param('namespace');
    my $user = $config->param('username');
    my $pass = $config->param('password');

    my $command = "curl -s -X POST -H \"Content-Type: text/xml\" -H \"SOAPAction: $namespace/$myget\" -d ' <soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"$namespace\"> <soapenv:Header/> <soapenv:Body> <web:$myget/> </soapenv:Body> </soapenv:Envelope> ' -u $user:$pass $endpoint";
    my $response = `$command`;
    # check  if curl command was successful
    if ($? != 0) {
        print "Error: $response\n";
        $logger->error("Error: $response");
        exit 1;
    }
    return $response;

}
