/*
 *  Author: Samuel Abels <spam debain org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "dispatcher.h"

//#define _DEBUG_

extern GUIMainwindow* mainwindow;


/******************************************************************************
 * Constructor/Destructor
 ******************************************************************************/
Dispatcher::Dispatcher()
{
#ifdef _DEBUG_
  printf("Dispatcher::Dispatcher(): Called.\n");
#endif
  mainwindow->ipv4_analyzer.signal_ip_changed.connect(
       sigc::mem_fun(*this, &Dispatcher::on_ipv4_analyzer_ip_changed));
  mainwindow->ipv4_analyzer.signal_mask_changed.connect(
       sigc::mem_fun(*this, &Dispatcher::on_ipv4_analyzer_mask_changed));
  mainwindow->ipv4_analyzer.signal_pfxlen_changed.connect(
       sigc::mem_fun(*this, &Dispatcher::on_ipv4_analyzer_pfxlen_changed));
  mainwindow->ipv4_subnet_calculator.signal_range_changed.connect(
       sigc::mem_fun(*this, &Dispatcher::on_ipv4_subnet_calculator_range_changed));
  mainwindow->ipv4_subnet_splitter.signal_changed.connect(
       sigc::mem_fun(*this, &Dispatcher::on_ipv4_subnet_splitter_changed));
  
  // Initialize with the default values.
  unsigned long ip = 0, mask = 0;
  ipv4_ip2integer("192.168.0.1",   &ip);
  ipv4_ip2integer("255.255.255.0", &mask);
  mainwindow->ipv4_analyzer.set_mask(mask);
  mainwindow->ipv4_analyzer.set_ip(ip);
}


Dispatcher::~Dispatcher()
{
#ifdef _DEBUG_
  printf("Dispatcher::~Dispatcher(): Called.\n");
#endif
}


/******************************************************************************
 * Public
 ******************************************************************************/


/******************************************************************************
 * Protected
 ******************************************************************************/
void Dispatcher::get_prefixes_from_range(unsigned long from, unsigned long to)
{
  Prefix* prefixes[2000];
  ipv4_get_prefixes_from_range(from, to, prefixes);
}


void Dispatcher::on_ipv4_analyzer_ip_changed(unsigned long ip,
                                             unsigned long mask)
{
#ifdef _DEBUG_
  printf("Dispatcher::on_ipv4_analyzer_ip_changed(): Called.\n");
#endif
  mainwindow->lock_signals();
  unsigned long broadcast = 0;
  ipv4_get_broadcast(ip, mask, &broadcast);
  mainwindow->ipv4_analyzer.set_output_range(ip & mask, broadcast);
  mainwindow->ipv4_analyzer.set_output_network(ip & mask);
  mainwindow->ipv4_analyzer.set_output_broadcast(broadcast);
  mainwindow->ipv4_analyzer.set_output_bin_ip(ip);
  mainwindow->ipv4_analyzer.set_output_bin_network(ip & mask);
  mainwindow->ipv4_analyzer.set_output_bin_broadcast(broadcast);
  mainwindow->ipv4_analyzer.set_output_hex_ip(ip);
  mainwindow->ipv4_analyzer.set_output_hex_network(ip & mask);
  mainwindow->ipv4_analyzer.set_output_hex_broadcast(broadcast);
  mainwindow->unlock_signals();
}


void Dispatcher::on_ipv4_analyzer_mask_changed(unsigned long ip,
                                               unsigned long mask)
{
#ifdef _DEBUG_
  printf("Dispatcher::on_ipv4_analyzer_mask_changed(): Called.\n");
#endif
  mainwindow->lock_signals();
  unsigned short int pfxlen       = 0;
  unsigned long      broadcast    = 0;
  unsigned int       numsubnets   = 0;
  unsigned int       numhosts     = 0;
  unsigned int       numhosts_all = 0;
  ipv4_get_broadcast(ip, mask, &broadcast);
  if (ipv4_mask2pfxlen(mask, &pfxlen) == 0)
    mainwindow->ipv4_analyzer.set_pfxlen(pfxlen);
  ipv4_get_num_subnets(pfxlen, &numsubnets);
  ipv4_get_num_hosts(pfxlen, &numhosts);
  ipv4_get_num_hosts_all(pfxlen, &numhosts_all);
  mainwindow->ipv4_analyzer.set_output_range(ip & mask, broadcast);
  mainwindow->ipv4_analyzer.set_output_subnets(numsubnets);
  mainwindow->ipv4_analyzer.set_output_hosts(numhosts);
  mainwindow->ipv4_analyzer.set_output_hosts_all(numhosts_all);
  mainwindow->ipv4_analyzer.set_output_network(ip & mask);
  mainwindow->ipv4_analyzer.set_output_broadcast(broadcast);
  mainwindow->ipv4_analyzer.set_output_bin_mask(mask);
  mainwindow->ipv4_analyzer.set_output_bin_broadcast(broadcast);
  mainwindow->ipv4_analyzer.set_output_hex_mask(mask);
  mainwindow->ipv4_analyzer.set_output_hex_broadcast(broadcast);
  mainwindow->unlock_signals();
}


void Dispatcher::on_ipv4_analyzer_pfxlen_changed(unsigned long ip,
                                                 unsigned short int pfxlen)
{
#ifdef _DEBUG_
  printf("Dispatcher::on_ipv4_analyzer_pfxlen_changed(): Called.\n");
#endif
  mainwindow->lock_signals();
  unsigned long mask         = 0;
  unsigned long broadcast    = 0;
  unsigned int  numsubnets   = 0;
  unsigned int  numhosts     = 0;
  unsigned int  numhosts_all = 0;
  ipv4_pfxlen2mask(pfxlen, &mask);
  ipv4_get_broadcast(ip, mask, &broadcast);
  ipv4_get_num_subnets(pfxlen, &numsubnets);
  ipv4_get_num_hosts(pfxlen, &numhosts);
  ipv4_get_num_hosts_all(pfxlen, &numhosts_all);
  mainwindow->ipv4_analyzer.set_mask(mask);
  mainwindow->ipv4_analyzer.set_output_range(ip & mask, broadcast);
  mainwindow->ipv4_analyzer.set_output_subnets(numsubnets);
  mainwindow->ipv4_analyzer.set_output_hosts(numhosts);
  mainwindow->ipv4_analyzer.set_output_hosts_all(numhosts_all);
  mainwindow->ipv4_analyzer.set_output_network(ip & mask);
  mainwindow->ipv4_analyzer.set_output_broadcast(broadcast);
  mainwindow->ipv4_analyzer.set_output_bin_mask(mask);
  mainwindow->ipv4_analyzer.set_output_bin_broadcast(broadcast);
  mainwindow->ipv4_analyzer.set_output_hex_mask(mask);
  mainwindow->ipv4_analyzer.set_output_hex_broadcast(broadcast);
  mainwindow->unlock_signals();
}


void Dispatcher::on_ipv4_subnet_calculator_range_changed(unsigned long from,
                                                         unsigned long to)
{
#ifdef _DEBUG_
  printf("Dispatcher::on_ipv4_subnet_calculator_range_changed(): Called.\n");
#endif
  mainwindow->lock_signals();
  if (from > to)
    to = from;
  mainwindow->ipv4_subnet_calculator.set_range(from, to);
  mainwindow->ipv4_subnet_calculator.prefixlist.clear();
  Prefix* prefixes[1000];
  prefixes[0] = NULL;
  if (ipv4_get_prefixes_from_range(from, to, prefixes) == 0)
    mainwindow->ipv4_subnet_calculator.prefixlist.insert(prefixes);
  ipv4_free_prefixlist(prefixes);
  mainwindow->unlock_signals();
}


void Dispatcher::on_ipv4_subnet_splitter_changed(unsigned long from,
                                                 unsigned long to,
                                                 unsigned short int pfxlen)
{
#ifdef _DEBUG_
  printf("Dispatcher::on_ipv4_subnet_splitter_changed(): Called.\n");
#endif
  mainwindow->lock_signals();
  if (from > to)
    to = from;
  mainwindow->ipv4_subnet_splitter.set_range(from, to);
  mainwindow->ipv4_subnet_splitter.prefixlist.clear();
  Prefix* prefixes[1000 + 1];
  prefixes[0] = NULL;
  if (ipv4_get_prefixes_from_range_flsm(from, to, pfxlen, prefixes, 1000) == 0)
    mainwindow->ipv4_subnet_splitter.prefixlist.insert(prefixes);
  ipv4_free_prefixlist(prefixes);
  mainwindow->unlock_signals();
}
