#ifndef NETSERVER_H
#define NETSERVER_H

#include "ipv4/lwip/ip_addr.h"
#include "lwip/netif.h"
#include "netif/etharp.h"

namespace mbed {
  class TCPListener;
  class TCPCallbackListener;
  class TCPConnection;

  /**
   * Network main class
   * provides the basic network features.
   */
  class NetServer {
    public:
      /**
       * Default constructor tryes to bring the network interface up with dhcp.
       */
      NetServer();
      /**
       * Constructor for fix ip setting
       */
      NetServer(struct ip_addr me_ip, struct ip_addr netmask, struct ip_addr gateway);
      ~NetServer();
      
      /**
       * Set a diffrent ethernet address
       */
      void setMAC(const struct eth_addr &value) { mac = value; }
      
      /**
       * Get the current ethernet address
       */
      const struct eth_addr &getMAC() { return mac; }
      
      /**
       * Set MBed IP Address
       */
      void setIPAddr(const struct ip_addr &value) { ipaddr = value; }
      /**
       * Get MBed IP Address
       */
      const struct ip_addr &getIPAddr() { return ipaddr; }
      
      /**
       * Set Netmask
       */
      void setNetmask(const struct ip_addr &value) { netmask = value; }
      
      /**
       * Get Netmask
       */
      const struct ip_addr &getNetmask() { return netmask; }

      /**
       * Set default Gateway
       */
      void setGateway(const struct ip_addr &value) { gateway = value; }
      
      /**
       * Get default Gateway
       */
      const struct ip_addr &getGateway() { return gateway; }
      
      /**
       * Set first Domain Name Server
       */
      void setDNS1(const struct ip_addr &value) { firstdns = value; }
      
      /**
       * Get first Domain Name Server
       */
      const struct ip_addr &getDNS1() { return firstdns; }
      
      /**
       * Set second Domain Name Server
       */
      void setDNS2(const struct ip_addr &value) { seconddns = value; }
      
      /**
       * Get second Domain Name Server
       */
      const struct ip_addr &getDNS2() { return seconddns; }
      
      /**
       * Set MBed Hostname
       */
      void setHostname(char *value) { hostname = value; }
      
      /**
       * Get MBed Hostname
       */
      char *getHostname() { return hostname; }
      
      /**
       * Define if DHCP sould be used.
       * @param value Bool if true dhcp is used else a static ip setting is assumed.
       */
      void setUseDHCP(const bool &value) { dhcp = value; }
      
      /**
       * Is the mbed board trying to use DHCP?
       */
      const bool &getUseDHCP() { return dhcp; }

      /**
       * Initialise the network environment. Set up all services.
       * Please call after configuration.
       */
      void init();

      /**
       * Set the network interface up.
       * To enable the network interface after calling setDown()
       * Automaticly called from init().
       */
      void setUp();
      
      /**
       * Set the network interface down.
       * To disable the network interface temporary.
       * To make the interface avalible again use setUp().
       */
      void setDown();
      
      /**
       * This function waits until the network interface is Up.
       * To use to wait after init with DHCP. Helps continue work 
       * after the network interface is completly up.
       */
      void waitForDHCP();


      TCPCallbackListener *bindTCPPort(u16_t, err_t (*)(TCPCallbackListener *, struct tcp_pcb *, err_t));
      TCPListener *bindTCPPort(TCPListener *listener);
      void etablishTCPConnection(TCPConnection *);
    private:
      void emac_tmr();
      
      struct netif   *netif;
      struct netif    netif_data;

      struct eth_addr mac;
      
      struct ip_addr  ipaddr;
      struct ip_addr  netmask;
      struct ip_addr  gateway;
      
      struct ip_addr  firstdns;
      struct ip_addr  seconddns;
      
      bool            dhcp;
      
      Ticker tickFast, tickSlow, tickARP, eth_tick, dns_tick, dhcp_coarse, dhcp_fine;
      char *hostname;
  };

};
#endif /* NETSERVER_H */