package PMG::API2::Transport;

use strict;
use warnings;
use Data::Dumper;

use PVE::SafeSyslog;
use PVE::Tools qw(extract_param);
use HTTP::Status qw(:constants);
use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
use PVE::INotify;

use PMG::Config;

use base qw(PVE::RESTHandler);

__PACKAGE__->register_method ({
    name => 'index',
    path => '',
    method => 'GET',
    description => "List transport map entries.",
    proxyto => 'master',
    parameters => {
	additionalProperties => 0,
	properties => {},
    },
    returns => {
	type => 'array',
	items => {
	    type => "object",
	    properties => {
		domain => { type => 'string' },
		host => { type => 'string' },
		port => { type => 'integer' },
		use_mx => { type => 'boolean' },
		comment => { type => 'string'},
	    },
	},
	links => [ { rel => 'child', href => "{id}" } ],
    },
    code => sub {
	my ($param) = @_;

	my $tmap = PVE::INotify::read_file('transport');

	my $res = [];

	foreach my $domain (sort keys %$tmap) {
	    push @$res, $tmap->{$domain};
	}

	return $res;
    }});

__PACKAGE__->register_method ({
    name => 'create',
    path => '',
    method => 'POST',
    proxyto => 'master',
    protected => 1,
    description => "Add transport map entry.",
    parameters => {
	additionalProperties => 0,
	properties => {
	    domain => {
		description => "Domain name.",
		type => 'string', format => 'transport-domain',
	    },
	    host => {
		description => "Target host (name or IP address).",
		type => 'string', format => 'address',
	    },
	    port => {
		description => "SMTP port.",
		type => 'integer',
		minimum => 1,
		maximum => 65535,
		optional => 1,
		default => 25,
	    },
	    use_mx => {
		description => "Enable MX lookups.",
		type => 'boolean',
		optional => 1,
		default => 1,
	    },
	    comment => {
		description => "Comment.",
		type => 'string',
		optional => 1,
	    },
	},
    },
    returns => { type => 'null' },
    code => sub {
	my ($param) = @_;

	my $code = sub {

	    my $tmap = PVE::INotify::read_file('transport');

	    die "Transport map entry '$param->{domain}' already exists\n"
		if $tmap->{$param->{domain}};

	    $tmap->{$param->{domain}} = {
		domain => $param->{domain},
		host => $param->{host},
		port => $param->{port} // 25,
		use_mx => $param->{use_mx} // 1,
		comment => $param->{comment} // '',
	    };

	    PVE::INotify::write_file('transport', $tmap);

	    PMG::Config::postmap_pmg_transport();
	};

	PMG::Config::lock_config($code, "add transport map entry failed");

	return undef;
    }});

__PACKAGE__->register_method ({
    name => 'read',
    path => '{domain}',
    method => 'GET',
    description => "Read transport map entry.",
    proxyto => 'master',
    parameters => {
	additionalProperties => 0,
	properties => {
	    domain => {
		description => "Domain name.",
		type => 'string', format => 'transport-domain',
	    },
	},
    },
    returns => {
	type => "object",
	properties => {
	    domain => { type => 'string'},
	    host => { type => 'string'},
	    port => { type => 'integer'},
	    use_mx => { type => 'boolean'},
	    comment => { type => 'string'},
	},
    },
    code => sub {
	my ($param) = @_;

	my $tmap = PVE::INotify::read_file('transport');

	if (my $entry = $tmap->{$param->{domain}}) {
	    return $entry;
	}

	die "Transport map entry '$param->{domain}' does not exist\n";
    }});

__PACKAGE__->register_method ({
    name => 'write',
    path => '{domain}',
    method => 'PUT',
    description => "Update transport map entry.",
    protected => 1,
    proxyto => 'master',
    parameters => {
	additionalProperties => 0,
	properties => {
	    domain => {
		description => "Domain name.",
		type => 'string', format => 'transport-domain',
	    },
	    host => {
		description => "Target host (name or IP address).",
		type => 'string', format => 'address',
		optional => 1,
	    },
	    port => {
		description => "SMTP port.",
		type => 'integer',
		minimum => 1,
		maximum => 65535,
		optional => 1,
	    },
	    use_mx => {
		description => "Enable MX lookups.",
		type => 'boolean',
		optional => 1,
	    },
	    comment => {
		description => "Comment.",
		type => 'string',
		optional => 1,
	    },
	},
    },
    returns => { type => 'null' },
    code => sub {
	my ($param) = @_;

	my $code = sub {

	    my $tmap = PVE::INotify::read_file('transport');

	    my $domain = extract_param($param, 'domain');

	    my $data = $tmap->{$domain};

	    die "Transport map entry '$param->{domain}' does not exist\n" if !$data;

	    die "no options specified\n" if !scalar(keys %$param);

	    for my $prop (qw(host port use_mx comment)) {
		$data->{$prop} = $param->{$prop} if defined($param->{$prop});
	    }

	    PVE::INotify::write_file('transport', $tmap);

	    PMG::Config::postmap_pmg_transport();
	};

	PMG::Config::lock_config($code, "update transport map entry failed");

	return undef;
    }});

__PACKAGE__->register_method ({
    name => 'delete',
    path => '{domain}',
    method => 'DELETE',
    description => "Delete a transport map entry",
    protected => 1,
    proxyto => 'master',
    parameters => {
	additionalProperties => 0,
	properties => {
	    domain => {
		description => "Domain name.",
		type => 'string', format => 'transport-domain',
	    },
	}
    },
    returns => { type => 'null' },
    code => sub {
	my ($param) = @_;

	my $code = sub {

	    my $tmap = PVE::INotify::read_file('transport');

	    die "Transport map entry '$param->{domain}' does not exist\n"
		if !$tmap->{$param->{domain}};

	    delete $tmap->{$param->{domain}};

	    PVE::INotify::write_file('transport', $tmap);

	    PMG::Config::postmap_pmg_transport();
	};

	PMG::Config::lock_config($code, "delete transport map extry failed");

	return undef;
    }});

1;
