package PVE::LXC::Setup::Gentoo;

use strict;
use warnings;

use File::Path 'make_path';

use PVE::LXC::Setup::Base;

use base qw(PVE::LXC::Setup::Base);

sub new {
    my ($class, $conf, $rootdir) = @_;

    my $version = PVE::Tools::file_read_firstline("$rootdir/etc/gentoo-release");
    die "unable to read version info\n" if !defined($version);
    if ($version =~ /^gentoo base system release (.*)$/i) {
	$version = $1;
    } else {
	die "unrecognized gentoo version: $version\n";
    }

    my $self = { conf => $conf, rootdir => $rootdir, version => 0 };

    $conf->{ostype} = "gentoo";

    return bless $self, $class;
}

# Gentoo doesn't support the /dev/lxc/ subdirectory
sub devttydir {
    return '';
}

sub template_fixup {
    my ($self, $conf) = @_;
    $self->setup_securetty($conf);

    $self->remove_lxc_name_from_etc_hosts();
}

sub setup_init {
    my ($self, $conf) = @_;

    my $filename = "/etc/inittab";
    my $ttycount =  PVE::LXC::Config->get_tty_count($conf);
    my $inittab = $self->ct_file_get_contents($filename);

    my @lines = grep {
	    # remove getty lines
	    !/^\s*c?\d+:\d*:[^:]*:.*getty/
    } split(/\n/, $inittab);

    $inittab = join("\n", @lines) . "\n";

    for (my $id = 1; $id <= $ttycount; $id++) {
	next if $id == 7; # reserved for X11
	$inittab .= "$id\::respawn:/sbin/agetty 38400 tty$id\n";
    }

    $self->ct_file_set_contents($filename, $inittab);
}

sub setup_network {
    my ($self, $conf) = @_;

    # Gentoo's /etc/conf.d/net is supposed to only contains variables, but is
    # in fact sourced by a shell, so reading out existing modules/config values
    # is pretty inconvenient.
    # We SHOULD check for whether iproute2 or ifconfig is already being used,
    # but for now we just assume ifconfig (since they also state iproute2 might
    # not be available in a default setup, though the templates usually do have
    # it installed - we might just get away with an if/else clause to insert
    # ifconfig/iproute2 syntax as needed, that way we don't need to parse this
    # file even to support both...)

    my %modules = (ifconfig => 1);

    my $data = '';
    my %up;

    my $filename = "/etc/conf.d/net";

    foreach my $k (keys %$conf) {
	next if $k !~ m/^net(\d+)$/;
	my $d = PVE::LXC::Config->parse_lxc_network($conf->{$k});
	my $name = $d->{name};
	next if !$name;

	my $has_ipv4 = 0;
	my $has_ipv6 = 0;

	my $config = '';
	my $routes = '';

	if (defined(my $ip = $d->{ip})) {
	    if ($ip eq 'dhcp') {
		#$modules{dhclient} = 1; # Well, we could...
		$config .= "dhcp\n";
		$up{$name} = 1;
	    } elsif ($ip ne 'manual') {
		$has_ipv4 = 1;
		$config .= "$ip\n";
		$up{$name} = 1;
	    }
	}
	if (defined(my $gw = $d->{gw})) {
	    if ($has_ipv4 && !PVE::Network::is_ip_in_cidr($gw, $d->{ip}, 4)) {
		$routes .= "-host $gw dev $name\n";
	    }
	    $routes .= "default gw $gw\n";
	    $up{$name} = 1;
	}

	if (defined(my $ip = $d->{ip6})) {
	    if ($ip eq 'dhcp') {
		# FIXME: The default templates seem to only ship busybox' udhcp
		# client which means we're in the same boat as alpine linux.
		# They also don't provide dhcpv6-only at all - for THAT however
		# there are patches from way back in 2013 (bug#450326 on
		# gentoo.org's netifrc)... but whatever, # that's only 10 years
		# after the RFC3315 release (DHCPv6).
		#
		# So no dhcpv6(-only) setups here for now.

		#$modules{dhclientv6} = 1;
		#$config .= "dhcpv6\n";
		#$up{$name} = 1;
	    } elsif ($ip ne 'manual') {
		$has_ipv6 = 1;
		$config .= "$ip\n";
		$up{$name} = 1;
	    }
	}
	if (defined(my $gw = $d->{gw6})) {
	    if ($has_ipv6 && !PVE::Network::is_ip_in_cidr($gw, $d->{ip6}, 4)) {
		$routes .= "-6 -host $gw dev $name\n";
	    }
	    $routes .= "-6 default gw $gw\n";
	    $up{$name} = 1;
	}

	chomp $config;
	chomp $routes;
	$data .= "config_$name=\"$config\"\n" if $config;
	$data .= "routes_$name=\"$routes\"\n" if $routes;
    }

    $data = "modules=\"\$modules " . join(' ', sort keys %modules) . "\"\n" . $data;

    # We replace the template's default file...
    $self->ct_modify_file($filename, $data, replace => 1);

    foreach my $iface (keys %up) {
	$self->ct_symlink("net.lo", "/etc/init.d/net.$iface");
    }
}

sub set_hostname {
    my ($self, $conf) = @_;

    my $hostname = $conf->{hostname} || 'localhost';

    my $namepart = ($hostname =~ s/\..*$//r);

    my $hostname_fn = "/etc/conf.d/hostname";

    my $oldname = 'localhost';
    my $fh = $self->ct_open_file_read($hostname_fn);
    while (defined(my $line = <$fh>)) {
	chomp $line;
	next if $line =~ /^\s*(#.*)?$/;
	if ($line =~ /^\s*hostname=("[^"]*"|'[^']*'|\S*)\s*$/) {
	    $oldname = $1;
	    last;
	}
    }
    $fh->close();

    my ($ipv4, $ipv6) = PVE::LXC::get_primary_ips($conf);
    my $hostip = $ipv4 || $ipv6;

    my ($searchdomains) = $self->lookup_dns_conf($conf);

    $self->update_etc_hosts($hostip, $oldname, $hostname, $searchdomains);

    # This is supposed to contain only the hostname, so we just replace the
    # file.
    $self->ct_file_set_contents($hostname_fn, "hostname=\"$namepart\"\n");
}

1;
