/*
 *(C) 2004 by Sebastian Ortwein <kron@animeland.de>
 *
 * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <ctype.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <typeinfo>

#include <vdr/osdbase.h>
#include <vdr/osd.h>
#include <vdr/menuitems.h>
#include <vdr/status.h>
#include <vdr/recording.h>
#include <vdr/interface.h>
#include <vdr/config.h>

#include "menu.h"
#include "i18n.h"
#include "setup.h"
#include "readwriteconfs.h"

// --- cMenuEditIP ---------------------------------------------------------

cMenuEditIP::cMenuEditIP(const char *Name)
{
  name = strdup(Name);
  valuea = NULL;
  valueb = NULL;
  valuec = NULL;
  valued = NULL;
}

cMenuEditIP::~cMenuEditIP()
{
  free(name);
  free(valuea);
  free(valueb);
  free(valuec);
  free(valued);
}

void cMenuEditIP::SetValue(const char *Valuea, const char *Valueb, const char *Valuec, const char *Valued)
{
  free(valuea);
  free(valueb);
  free(valuec);
  free(valued);
  valuea = strdup(Valuea);
  valueb = strdup(Valueb);
  valuec = strdup(Valuec);
  valued = strdup(Valued);
  char *buffer = NULL;
  asprintf(&buffer, "%s:\t%s.%s.%s.%s", name, valuea, valueb, valuec, valued);
  SetText(buffer, false);
//  Display();
}

// --- cMenuEditIntIP ------------------------------------------------------

cMenuEditIntIP::cMenuEditIntIP(const char *Name, int *Valuea, int *Valueb, int *Valuec, int *Valued)
:cMenuEditIP(Name)
{
  valuea = Valuea;
  valueb = Valueb;
  valuec = Valuec;
  valued = Valued;
  min = 0;
  max = 256;
  editpos = 1;
  Set();
}

void cMenuEditIntIP::Set(void)
{
  char bufa[16];
  char bufb[16];
  char bufc[16];
  char bufd[16];
  if (editpos == 1)
	  snprintf(bufa, sizeof(bufa), "<%d>", *valuea);
  else
	  snprintf(bufa, sizeof(bufa), "%d", *valuea);
  if (editpos == 2)
	  snprintf(bufb, sizeof(bufb), "<%d>", *valueb);
  else
	  snprintf(bufb, sizeof(bufb), "%d", *valueb);
  if (editpos == 3)
	  snprintf(bufc, sizeof(bufc), "<%d>", *valuec);
  else
	  snprintf(bufc, sizeof(bufc), "%d", *valuec);
  if (editpos == 4)
	  snprintf(bufd, sizeof(bufd), "<%d>", *valued);
  else
	  snprintf(bufd, sizeof(bufd), "%d", *valued);
  SetValue(bufa, bufb, bufc, bufd);
}

eOSState cMenuEditIntIP::ProcessKey(eKeys Key)
{
  eOSState state = cMenuEditIP::ProcessKey(Key);
   
  if (state == osUnknown) {
	  switch (editpos) {
	    case 1:
			newValue = *valuea;
			break;
		case 2:
			newValue = *valueb;
			break;
		case 3:
			newValue = *valuec;
			break;
		case 4:
			newValue = *valued;
			break;
	  }

     Key = NORMALKEY(Key);
	 neweditpos = editpos;

     switch (Key) {
       case kNone: break;
       case k0 ... k9:
            if (fresh) {
               newValue = 0;
               fresh = false;
               }
            newValue = newValue * 10 + (Key - k0);
            break;
		case kLeft:
			if (editpos > 1)
				neweditpos = editpos - 1;
			fresh = true;
			break;
		case kRight:
			if (editpos < 4)
				neweditpos = editpos + 1;
			fresh = true;
			break;
       default:
            if (*valuea < min) { *valuea = min; Set(); }
            if (*valueb < min) { *valueb = min; Set(); }
            if (*valuec < min) { *valuec = min; Set(); }
            if (*valued < min) { *valued = min; Set(); }
            if (*valuea > max) { *valuea = max; Set(); }
            if (*valueb > max) { *valueb = max; Set(); }
            if (*valuec > max) { *valuec = max; Set(); }
            if (*valued > max) { *valued = max; Set(); }
            return state;
	 }

     if ((!fresh || min <= newValue) && newValue <= max) {
		 switch (editpos) {
	       case 1:
			   *valuea = newValue;
			   break;
		   case 2:
			   *valueb = newValue;
			   break;
		   case 3:
			   *valuec = newValue;
			   break;
		   case 4:
			   *valued = newValue;
			   break;
		 }

		 editpos = neweditpos;
		 Set();
	 }
	 state = osContinue;
  }
  return state;
}


// --- cMenuSetupNetwork -----------------------------------------------------------

cMenuSetupNetwork::cMenuSetupNetwork(void)
{
	data=NetworkSetup;
	Set();
}

void cMenuSetupNetwork::Set(void)
{
	int current = Current();
	Clear();
    SetSection(tr("Network"));
    Add(new cMenuEditIntIP(tr("Setup.NETWORK$Name Server"),					&data.nameservera, &data.nameserverb, &data.nameserverc, &data.nameserverd));
	Add(new cMenuEditStraItem(tr("Setup.NETWORK$Networkcard"), &data.networkcard, I18nNumNetworkcards, Networkcards));

	if (data.networkcard == 0)
	{
		if (data.eth0 == true)
		{
			Add(new cMenuEditBoolItem(tr("Setup.NETWORK$Automatic start"),		&data.automatic_start_eth0));
			Add(new cMenuEditStraItem(tr("Setup.NETWORK$Modi"),				&data.modi_eth0, I18nNumModis, Modis));
			if (data.modi_eth0 == 1)
			{
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$IP Adress"),					&data.addressa_eth0, &data.addressb_eth0, &data.addressc_eth0, &data.addressd_eth0));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Netmask"),					&data.netmaska_eth0, &data.netmaskb_eth0, &data.netmaskc_eth0, &data.netmaskd_eth0));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Broadcast"),					&data.broadcasta_eth0, &data.broadcastb_eth0, &data.broadcastc_eth0, &data.broadcastd_eth0));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Gateway"),					&data.gatewaya_eth0, &data.gatewayb_eth0, &data.gatewayc_eth0, &data.gatewayd_eth0));
			}
		}
	}

	if (data.networkcard == 1)
	{
		if (data.eth1 == true)
		{
			Add(new cMenuEditBoolItem(tr("Setup.NETWORK$Automatic start"),		&data.automatic_start_eth1));
			Add(new cMenuEditStraItem(tr("Setup.NETWORK$Modi"),				&data.modi_eth1, I18nNumModis, Modis));
			if (data.modi_eth1 == 1)
			{
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$IP Adress"),					&data.addressa_eth1, &data.addressb_eth1, &data.addressc_eth1, &data.addressd_eth1));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Netmask"),					&data.netmaska_eth1, &data.netmaskb_eth1, &data.netmaskc_eth1, &data.netmaskd_eth1));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Broadcast"),					&data.broadcasta_eth1, &data.broadcastb_eth1, &data.broadcastc_eth1, &data.broadcastd_eth1));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Gateway"),					&data.gatewaya_eth1, &data.gatewayb_eth1, &data.gatewayc_eth1, &data.gatewayd_eth1));
			}
		}
	}

	if (data.networkcard == 2)
	{
		if (data.eth2 == true)
		{
			Add(new cMenuEditBoolItem(tr("Setup.NETWORK$Automatic start"),		&data.automatic_start_eth2));
			Add(new cMenuEditStraItem(tr("Setup.NETWORK$Modi"),				&data.modi_eth2, I18nNumModis, Modis));
			if (data.modi_eth2 == 1)
			{
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$IP Adress"),					&data.addressa_eth2, &data.addressb_eth2, &data.addressc_eth2, &data.addressd_eth2));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Netmask"),					&data.netmaska_eth2, &data.netmaskb_eth2, &data.netmaskc_eth2, &data.netmaskd_eth2));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Broadcast"),					&data.broadcasta_eth2, &data.broadcastb_eth2, &data.broadcastc_eth2, &data.broadcastd_eth2));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Gateway"),					&data.gatewaya_eth2, &data.gatewayb_eth2, &data.gatewayc_eth2, &data.gatewayd_eth2));
			}
		}
	}

	if (data.networkcard == 3)
	{
		if (data.eth3 == true)
		{
			Add(new cMenuEditBoolItem(tr("Setup.NETWORK$Automatic start"),		&data.automatic_start_eth3));
			Add(new cMenuEditStraItem(tr("Setup.NETWORK$Modi"),				&data.modi_eth3, I18nNumModis, Modis));
			if (data.modi_eth3 == 1)
			{
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$IP Adress"),					&data.addressa_eth3, &data.addressb_eth3, &data.addressc_eth3, &data.addressd_eth3));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Netmask"),					&data.netmaska_eth3, &data.netmaskb_eth3, &data.netmaskc_eth3, &data.netmaskd_eth3));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Broadcast"),					&data.broadcasta_eth3, &data.broadcastb_eth3, &data.broadcastc_eth3, &data.broadcastd_eth3));
				Add(new cMenuEditIntIP(tr("Setup.NETWORK$Gateway"),					&data.gatewaya_eth3, &data.gatewayb_eth3, &data.gatewayc_eth3, &data.gatewayd_eth3));
			}
		}
	}
	SetCurrent(Get(current));
}

eOSState cMenuSetupNetwork::ProcessKey(eKeys Key)
{  
  int modi0 = data.modi_eth0;
  int modi1 = data.modi_eth1;
  int modi2 = data.modi_eth2;
  int modi3 = data.modi_eth3;
  int networkcard = data.networkcard;

  eOSState state = cMenuSetupPage::ProcessKey(Key);

  if (data.modi_eth0 != modi0 || data.modi_eth1 != modi1 || data.modi_eth2 != modi2 || data.modi_eth3 != modi3)
  {
	  modi0=data.modi_eth0;
	  modi1=data.modi_eth1;	  
	  modi2=data.modi_eth2;
	  modi3=data.modi_eth3;
	  Set();
	  Display();
  }

  if (data.networkcard != networkcard)
  {
	  networkcard=data.networkcard;
	  Set();
	  Display();
  }


  return state;
}

void cMenuSetupNetwork::Store(void)
{
	addLoopbackDevice("lo", true);
	char bufnameserver[16];
	snprintf(bufnameserver, sizeof(bufnameserver), "%d.%d.%d.%d", data.nameservera, data.nameserverb, data.nameserverc, data.nameserverd);
	netSetNameserver(bufnameserver);
	if (data.eth0 == true) {
		switch (data.modi_eth0) {
		  case 0:
//			  if (!setDhcpAttributes("eth0", switchautomatic(data.automatic_start_eth0)))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		  case 1:
			  char bufaddress[16];
			  char bufnetmask[16];
			  char bufbroadcast[16];
			  char bufgateway[16];
			  snprintf(bufaddress, sizeof(bufaddress), "%d.%d.%d.%d", data.addressa_eth0, data.addressb_eth0, data.addressc_eth0, data.addressd_eth0);
			  snprintf(bufnetmask, sizeof(bufnetmask), "%d.%d.%d.%d", data.netmaska_eth0, data.netmaskb_eth0, data.netmaskc_eth0, data.netmaskd_eth0);
			  snprintf(bufbroadcast, sizeof(bufbroadcast), "%d.%d.%d.%d", data.broadcasta_eth0, data.broadcastb_eth0, data.broadcastc_eth0, data.broadcastd_eth0);
			  snprintf(bufgateway, sizeof(bufgateway), "%d.%d.%d.%d", data.gatewaya_eth0, data.gatewayb_eth0, data.gatewayc_eth0, data.gatewayd_eth0);
//			  if (!setStaticAttributes("eth0", switchautomatic(data.automatic_start_eth0), bufaddress, bufnetmask, bufbroadcast, bufgateway))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		}
	}
	if (data.eth1 == true) {
		switch (data.modi_eth1) {
		  case 0:
//			  if (!setDhcpAttributes("eth1", switchautomatic(data.automatic_start_eth1)))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		  case 1:
			  char bufaddress[16];
			  char bufnetmask[16];
			  char bufbroadcast[16];
			  char bufgateway[16];
			  snprintf(bufaddress, sizeof(bufaddress), "%d.%d.%d.%d", data.addressa_eth1, data.addressb_eth1, data.addressc_eth1, data.addressd_eth1);
			  snprintf(bufnetmask, sizeof(bufnetmask), "%d.%d.%d.%d", data.netmaska_eth1, data.netmaskb_eth1, data.netmaskc_eth1, data.netmaskd_eth1);
			  snprintf(bufbroadcast, sizeof(bufbroadcast), "%d.%d.%d.%d", data.broadcasta_eth1, data.broadcastb_eth1, data.broadcastc_eth1, data.broadcastd_eth1);
			  snprintf(bufgateway, sizeof(bufgateway), "%d.%d.%d.%d", data.gatewaya_eth1, data.gatewayb_eth1, data.gatewayc_eth1, data.gatewayd_eth1);
//			  if (!setStaticAttributes("eth1", switchautomatic(data.automatic_start_eth1), bufaddress, bufnetmask, bufbroadcast, bufgateway))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		}
	}
	if (data.eth2 == true) {
		switch (data.modi_eth2) {
		  case 0:
//			  if (!setDhcpAttributes("eth2", switchautomatic(data.automatic_start_eth2)))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		  case 1:
			  char bufaddress[16];
			  char bufnetmask[16];
			  char bufbroadcast[16];
			  char bufgateway[16];
			  snprintf(bufaddress, sizeof(bufaddress), "%d.%d.%d.%d", data.addressa_eth2, data.addressb_eth2, data.addressc_eth2, data.addressd_eth2);
			  snprintf(bufnetmask, sizeof(bufnetmask), "%d.%d.%d.%d", data.netmaska_eth2, data.netmaskb_eth2, data.netmaskc_eth2, data.netmaskd_eth2);
			  snprintf(bufbroadcast, sizeof(bufbroadcast), "%d.%d.%d.%d", data.broadcasta_eth2, data.broadcastb_eth2, data.broadcastc_eth2, data.broadcastd_eth2);
			  snprintf(bufgateway, sizeof(bufgateway), "%d.%d.%d.%d", data.gatewaya_eth2, data.gatewayb_eth2, data.gatewayc_eth2, data.gatewayd_eth2);
//			  if (setStaticAttributes("eth2", switchautomatic(data.automatic_start_eth2), bufaddress, bufnetmask, bufbroadcast, bufgateway))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		}
	}
	if (data.eth3 == true) {
		switch (data.modi_eth3) {
		  case 0:
//			  if (!setDhcpAttributes("eth3", switchautomatic(data.automatic_start_eth3)))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		  case 1:
			  char bufaddress[16];
			  char bufnetmask[16];
			  char bufbroadcast[16];
			  char bufgateway[16];
			  snprintf(bufaddress, sizeof(bufaddress), "%d.%d.%d.%d", data.addressa_eth3, data.addressb_eth3, data.addressc_eth3, data.addressd_eth3);
			  snprintf(bufnetmask, sizeof(bufnetmask), "%d.%d.%d.%d", data.netmaska_eth3, data.netmaskb_eth3, data.netmaskc_eth3, data.netmaskd_eth3);
			  snprintf(bufbroadcast, sizeof(bufbroadcast), "%d.%d.%d.%d", data.broadcasta_eth3, data.broadcastb_eth3, data.broadcastc_eth3, data.broadcastd_eth3);
			  snprintf(bufgateway, sizeof(bufgateway), "%d.%d.%d.%d", data.gatewaya_eth3, data.gatewayb_eth3, data.gatewayc_eth3, data.gatewayd_eth3);
//			  if (!setStaticAttributes("eth3", switchautomatic(data.automatic_start_eth3), bufaddress, bufnetmask, bufbroadcast, bufgateway))
//				  Interface->Error(tr("Error while saving settings!"));
			  break;
		}
	}
	if (data.eth0 == true) {
		system("ifdown eth0");
		system("ifup eth0");
	}
	if (data.eth1 == true) {
		system("ifdown eth1");
		system("ifup eth1");
	}
	if (data.eth2 == true) {
		system("ifdown eth2");
		system("ifup eth2");
	}
	if (data.eth3 == true) {
		system("ifdown eth3");
		system("ifup eth3");
	}
	NetworkSetup=data;
	
}
