# modulos
use warnings;
use strict;
use Win32::IPConfig;
use Net::NBName;
use Net::NetSend qw(:all);

# variables
my $version = '4';
my %chatconfig;

system("cls");

# reading config file
open(CONFIG,"<chat.conf") or die "Cannot read configuration file chat.conf: $!\n";

# small file, throw everything into memory is faster
my @content = <CONFIG>;
close(CONFIG);

my @temp;

foreach ( @content ) {

    next if $_ =~ /#/;
    next if $_ =~ /^\n$/;
    chomp;
    $_ =~ s/\s//g;
    @temp = split(/=/,$_);
    $chatconfig{$temp[0]} = $temp[1];
    @temp = ();

}	
@content = ();

my $userdb = $chatconfig{userdb};

open(FILE,"<$userdb") or die "cannot open file: $!";
@content = <FILE>;
close(FILE);

my %list;

# criando a lista de usuários. o usuário que esta rodando o
# programa não deve ser incluído no mesmo

my $owner;

foreach ( @content ) {
	
    next if $_ =~ /#/;
    next unless ($_ =~ /:/);
    chomp;
    @temp = split(/:/,$_);
    
    if ( $temp[0] eq $ENV{username} ) {

        $owner = $temp[1];
        next;

    }

    $list{$temp[1]} = $temp[0];
        
}

# ordenando os nomes da lista por apelidos (ordem crescente)
my @order;
my $index = 1;

foreach ( sort( keys( %list ) ) ) {

# forçando o array a começar do índice 1, já que faz mais sentido usar esse numero no menu
    $order[$index] = $_;
    $index++;

}

my $option;

while (0 < 1) {

print <<BLOCK;
----------------------------------------------------------
Programa de envio de mensagens do Seo Creysson versao $version

Ola $owner.
Escolha o sujeito para quem voce quer mandar uma mensagem:
BLOCK


    for ( $index = 1; $index < @order; $index++ ) {
	
        print $index, '. ', $order[$index], "\n";
    
    }

    my $broadcast = $index;
    print "$index. Broadcast para los hermanos\n";
    my $end = ++$index;
    print "$index. Sair\n";

    print "Opcao selecionada: ";
    $option = <STDIN>;

# teste de entrada de dados
    unless ( $option =~ /\d/ and $option >= 0 and $option <= $end ) {

        system("cls");

print <<BLOCK;
##################################
#Digite um numero valido animal !#
##################################
BLOCK
        next;

    }

# saída do programa

    if ($end == $option) {

        system('cls');
        print "Firma cara. Falouz.\n";
        print "-----------------------------------------------------------------\n\n";
        print "\t\t\tby Alceu (glasswalk3r\@yahoo.com.br)\n";
	    sleep 1;
	    exit;

    }


# definindo o destinatario para imprimir confirmacao

    my $destinatario;

    if ($broadcast == $option) {

        $destinatario = "BROADCAST";

    } else {

        $destinatario = $order[$option];
	
    }	


# definindo confirmacao e a mensagem

    print "Legal, agora digite a mensagem para > $destinatario <. Quando acabar, digite ENTER.\n";
    print "Se quiser abortar o envio, nao digite nada e pressione ENTER.\n\n";
    print "Mensagem: ";

    my $message = <STDIN>;

    if ($message =~ /^\n$/) {
	
	system("cls");
	print "A mensagem NAO foi enviada.\n";
	next;

    }

    chomp($message);

    if ($broadcast == $option) {
	
       system('cls');

       foreach ( values(%list) ) {

           send_message( $_, $owner, "[broadcast]: $message");
      
       }

       next;

    } else {
	
        system('cls');
        send_message( $list{$order[$option]}, $owner, $message );

    }

# fim do loop
}



#FUNCOES

# função para envio de mensagens

sub send_message {

    my $login = shift;
    my $source_netbios_name = shift;
    my $message = shift;
    
    my $target_ip = search_name($login);
    my $target_netbios_name;
    my $debug = 0;
    my $success;

    $target_netbios_name = getNbName($target_ip, $debug);
  
    die "No netbios name found: $@\n" unless ( defined( $target_netbios_name ) );

    $success = sendMsg($target_netbios_name, $source_netbios_name, $target_ip, $message, $debug);
    print ( $success ? "Mensagem entregue com sucesso\n" : "Ocorreu um erro na entrega da mensagem \n$@\n" );

}

# checa se o computador possui ao menos um servidor WINS configurado para evitar broadcast
# deveria permitir o uso de mais um adaptador (usar o chat.conf para determinar qual) e
# retornar uma lista de servidores WINS ao invés de somente o primeiro
sub check_wins {

    my $host = Win32::IPConfig->new();
    my @adapters = $host->get_adapters; 
    my @wins_servers;

# lets work with just the first adapter  
    @wins_servers = $adapters[0]->get_wins();
    
    ( @wins_servers > 0 ) ? return $wins_servers[0] : 0;

}

# queries thru WINS server or broadcast for machine name giving username
sub search_name {

    my $login = shift;
    my $query = Net::NBName->new();
    my $wins_server = check_wins();
    my $suffix = hex 3;
    my $host;
    
    if ( defined( $wins_server ) ) {

# debug
#        printf "querying %s for %s<%02X>...\n", $wins_server, $login, $suffix;
        $host = $query->name_query($wins_server, $login, $suffix);
    

# no WINS available, trying     
    } else {

# debug   
#        printf "broadcasting for %s<%02X>...\n", $login, $suffix;
        $host = $query->name_query(undef, $login, $suffix);
    
    }

# ugly, but the module doesn't give me a clear interface
    my @list = $host->addresses; 
    return $list[0]->{address};

}
