package ip;

use warnings;
use strict;

use Data::Dump qw/dump/;

use html;
use server;

sub lines {
	my ( $object ) = @_;

	my $debug = server::debug();

	$object ||= 'link';

	my $i = 0;
	my @objects;

	my @headers;
	my $headers;

	foreach my $line ( split(/\n/, `ip $object`) ) {
		warn "# $line\n" if $debug;
		my $add_header;

		if ( $line =~ s{^(\d+):\s+(\w+):\s+}{} ) {
			$i = $1;
			$objects[$i] = { dev => $2 };
			$add_header = $object;
		} elsif ( $line =~ s{^\s+}{} ) {
			# line continues
		} else {
			$i++;
			$line =~ s{^(\S+)\s+}{};
			$objects[$i] = {
				$object => $1
			};
			$add_header = $object;
		}

		push @headers, $add_header if $add_header && ! $headers->{$add_header}++;

		if ( $line =~ s{<(\S+)>\s+}{} ) {
			$add_header = 'flags';
			$objects[$i]->{$add_header} = $1;
			push @headers, $add_header unless $headers->{$add_header}++;
		}

		my @p = split(/\s+/, $line);
		while (@p) {
			my ($n,$v) = splice @p, 0, 2;
			if ( ! defined $v ) {
				$objects[$i]->{''} = $n;
				$n = '';
			} elsif ( $n =~ m{^(.+)/(.+)$} ) {
				$n = $1;
				$objects[$i]->{$n} = $2;
				$objects[$i]->{mac} = $v;
			} else {
				$objects[$i]->{$n} = $v;
			}
			push @headers, $n unless $headers->{$n}++;
		}

#		warn dump( $objects[$i] );
	}

	return unless @objects;

	$objects[0] = [ @headers ];

	return @objects;
}

sub html {
	my @objects = ip::lines( @_ );
	return '' unless @objects;

	my @headers = @{ shift @objects };

	my @table = ( -( $#headers + 1), @headers );
	foreach my $o ( @objects ) {
		foreach ( 0 .. $#headers ) {
			my $h = $headers[$_];
			push @table, $o->{$h};
		}
	}

	return html::table( @table );
}

sub devices_up {
	my @links = ip::lines( 'link' );
	my @devs;
	foreach ( 1 .. $#links ) {
		push @devs, $links[$_]->{dev} if $links[$_]->{flags} =~ m{UP};
	}
	return @devs;
}

sub default_route_dev {
	my @routes = ip::lines 'route';

	return
		map { $_->{dev} }
		grep { $_->{route} eq 'default' }
		splice @routes, 1 # FIXME ship header
	;
}

sub to_int {
	unpack( 'N', pack( 'C*', split(/\./, shift) ) )
}

sub from_int {
	join( '.', unpack('C4', pack('N',shift)) )
}

sub in_dhcp_range {
	my $ip = shift;
	my $i = to_int($ip) & to_int($server::netmask);
	my $s = to_int($server::ip) & to_int($server::netmask);

	if ( $i == $s ) {
		$i = to_int($ip) & ( to_int($server::netmask) ^ 0xffffffff );
		return 1 if ( $i >= $server::ip_from && $i <= $server::ip_to );
	}
	return 0;
}

1;
