#include <ctype.h>
#include <stdio.h>
#ifdef SYSV
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"

#ifndef WINDOWS
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#endif

#include "mush.h"


DESCRIPTOR_DATA *connectiond[5];
int outgoing[5];
char connection_names[5][5];

void 
randpop (CHAR_DATA * ch, char *argy)
{
  char arg1[150];
  char arg2[150];
  int i;
  int freepos;
  int pct;
  int mobbie;
  int objn;
  DEFINE_COMMAND ("randpop", randpop, POSITION_DEAD, 110, LOG_ALWAYS, "Unfinished command... not recommended to use.")
#ifdef NEW_WORLD
    argy = one_argy (argy, arg1);
  argy = one_argy (argy, arg2);
  if (!str_cmp (arg1, "crashtest"))
    {
      OBJ_PROTOTYPE *o;
      o = NULL;
      if (o->weight < 5)
	{
	  fprintf (stderr, "Got here.\n");
	}
    }
  if (arg1[0] == '\0')
    {
      hugebuf_o[0] = '\0';
      sprintf (hugebuf_o, "Vnum %%/250 [Mob Vnums]\n\r");
      sprintf (hugebuf_o + strlen (hugebuf_o), "-----------------------------------------------------------------------\n\r");
      for (i = 0; i < MAX_RANDOMPOP; i++)
	{
	  if (g_obj_pop[i] == 0)
	    continue;
	  sprintf (hugebuf_o + strlen (hugebuf_o), "%-5d  %-3d  %d %d %d %d %d %d %d %d %d %d\n\r",
		   g_obj_pop[i], g_percent[i],
		   g_moblist[i][0],
		   g_moblist[i][1],
		   g_moblist[i][2],
		   g_moblist[i][3],
		   g_moblist[i][4],
		   g_moblist[i][5],
		   g_moblist[i][6],
		   g_moblist[i][7],
		   g_moblist[i][8],
		   g_moblist[i][9]);
	}
      page_to_char (hugebuf_o, ch);
      return;
    }

  if (!str_cmp (arg1, "OBJ"))
    {
      freepos = -1;
      for (i = 0; i < MAX_RANDOMPOP; i++)
	{
	  if (g_obj_pop[i] == 0)
	    {
	      freepos = i;
	      break;
	    }
	}
      if (freepos == -1)
	{
	  send_to_char ("No more free!\n\r", ch);
	  return;
	}
      if (!is_number (arg2) || !is_number (argy))
	{
	  send_to_char ("Must specify object vnum.\n\r", ch);
	  return;
	}
      objn = atoi (arg2);
      if (objn != 0 && get_obj_index (objn) == NULL)
	{
	  send_to_char ("That object was not found.\n\r", ch);
	  return;
	}
      pct = atoi (argy);
      if (pct > 250)
	{
	  send_to_char ("Percent can't be more than 250!\n\r", ch);
	  return;
	}
      g_obj_pop[freepos] = objn;
      g_percent[freepos] = pct;
      send_to_char ("All set.  Use 'randpop <obj number> <mob>' to add mobs to the list.\n\r", ch);
      return;
    }

  if (is_number (arg1))
    {
      int looking_for;
      bool minus = FALSE;
      int slot = -1;
      looking_for = atoi (arg1);
      if (looking_for == 0)
	return;
      for (i = 0; i < MAX_RANDOMPOP; i++)
	{
	  if (g_obj_pop[i] == looking_for)
	    {
	      slot = i;
	      break;
	    }
	}
      if (slot == -1)
	{
	  send_to_char ("Object not found in list.\n\r", ch);
	  return;
	}
      if (!str_cmp (arg2, "delete"))
	{
	  g_obj_pop[slot] = 0;
	  send_to_char ("Deleted.\n\r", ch);
	  return;
	}
      if (arg2[0] == '-')
	{
	  char tmp[200];
	  minus = TRUE;
	  strcpy (tmp, arg2 + 1);
	  strcpy (arg2, tmp);
	}
      if (!is_number (arg2))
	return;
      mobbie = atoi (arg2);
      if (minus)
	{
	  for (i = 0; i < 10; i++)
	    {
	      if (g_moblist[slot][i] == mobbie)
		{
		  g_moblist[slot][i] = 0;
		  send_to_char ("Mob removed!\n\r", ch);
		  return;
		}
	    }
	  return;
	}
      if (mobbie >= 10000 || get_mob_index (mobbie) == NULL)
	{
	  send_to_char ("Mob not found or vnum above 10,000.\n\r", ch);
	  return;
	}

      for (i = 0; i < 10; i++)
	{
	  if (g_moblist[slot][i] == 0)
	    {
	      g_moblist[slot][i] = mobbie;
	      send_to_char ("Mob added!\n\r", ch);
	      g_mobpop[mobbie] = TRUE;
	      return;
	    }
	}
      send_to_char ("No free slots on that object.\n\r", ch);
      return;
    }
#endif
  return;
}

#ifndef WINDOWS

#ifdef NEED_EXTERN
extern void alarm ();
#endif

static void 
alarm_handler ()
{
  return;
}




int 
connect_remote (char *host, char *port, CHAR_DATA * ch)
{
  int sock, connectresult;
  struct sockaddr_in sockaddr;
  if (host[0] == '\0')
    return 0;
  if (isdigit (*host))
    sockaddr.sin_addr.s_addr = inet_addr (host);
  else
    {
      struct hostent *hp;
      if ((hp = gethostbyname (host)) == NULL)
	{
	  send_to_char ("Unknown host!\n\r", ch);
	  return 0;
	}
      memcpy ((char *) &sockaddr.sin_addr, hp->h_addr, sizeof (sockaddr.sin_addr));
    }

  if (isdigit (*port))
    sockaddr.sin_port = htons (atoi (port));
  else
    {
      send_to_char ("Must include port number!\n\r", ch);
      return 0;
    }

  if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
    {
      fprintf (stderr, "Error!\n");
      return 0;
    }

  sockaddr.sin_family = AF_INET;


  write_to_descriptor2 (ch->desc, "Trying to connect..", 0);

  if (signal (SIGALRM, alarm_handler) < 0)
    {
      return 0;
    }
  alarm (15);

  connectresult = connect (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
  alarm (0);

  if (connectresult)
    {
      close (sock);
      return 0;
    }
  return sock;
}

#endif

void 
mudlink (CHAR_DATA * ch, char *argy)
{
  int i;
  char arg1[500];
  char cnm[50];

#ifndef WINDOWS

  DEFINE_COMMAND ("mudlink", mudlink, POSITION_DEAD, 110, LOG_ALWAYS, "This command allows you to link the god/builder channels.")
    if (str_cmp ("Orin", NAME (ch)) && str_cmp("Palio",NAME(ch)) && str_cmp ("Smack", NAME (ch)))
    return;
  argy = one_argy (argy, cnm);
  if (strlen (cnm) != 3)
    {
      send_to_char ("You must give a 3 letter abbreviation for the destination MUD.\n\r", ch);
      return;
    }
  argy = one_argy (argy, arg1);
  for (i = 0; i < 5; i++)
    if (outgoing[i] == 0)
      break;
  if (i == 5)
    {
      send_to_char ("None free!\n\r", ch);
      return;
    }
  outgoing[i] = connect_remote (arg1, argy, ch);
  if (outgoing[i])
    {
      send_to_char ("Connection established!  Negotiation started.\n\r", ch);
      connectiond[i] = new_sdesc (outgoing[i]);
      write_to_descriptor2 (connectiond[i], "\n\rNewchannel\n\r", 0);
    }
  cnm[0] = UPPER (cnm[0]);
  cnm[1] = UPPER (cnm[1]);
  cnm[2] = UPPER (cnm[2]);
  strcpy (connection_names[i], cnm);

  write_to_descriptor2 (connectiond[i], "&c", 0);
  write_to_descriptor2 (connectiond[i], cnm, 0);
  write_to_descriptor2 (connectiond[i], "\n\r", 0);

#endif
  return;
}

void 
read_channel_data (void)
{
  FILE *fp;
  CHANNEL *c;
  CHANNEL *c_next;
  char buf[500];

  for (c = chan_first; c != NULL; c = c_next)
    {
      c_next = c->next;
      free_m (c);
    }
  chan_first = NULL;

  if ((fp = fopen ("channel.dat", "r")) == NULL)
    {
      fprintf (stderr, "Could not read channel.dat!\n");
      return;
    }

  c = NULL;
  for (;;)
    {
      strcpy (buf, fread_word (fp));
      if (!str_cmp ("END", buf))
	{
	  break;
	}
      if (!str_cmp ("#", buf))
	{
	  fread_to_eol (fp);
	  continue;
	}
      if (!str_cmp ("NEW_CHANNEL", buf))
	{
	  c = mem_alloc (sizeof (*c));
	  c->clan = FALSE;
	  c->clan2 = FALSE;
	  c->channel_name = &str_empty[0];
	  c->moves = 0;
	  c->commands[0] = NULL;
	  c->commands[1] = NULL;
	  c->commands[2] = NULL;
	  c->level = 0;
	  c->to_level = 0;
	  c->color = &str_empty[0];
	  c->to_align = SAME_ALIGN;
	  c->next = chan_first;
	  chan_first = c;
	  continue;
	}
      if (!str_cmp ("NAME", buf))
	{
	  c->channel_name = str_dup (fread_word (fp));
	  continue;
	}
      if (!str_cmp ("LEVEL", buf))
	{
	  c->level = fread_number (fp);
	  continue;
	}
      if (!str_cmp ("MOVES", buf))
	{
	  c->moves = fread_number (fp);
	  continue;
	}
      if (!str_cmp ("CLAN", buf))
	{
	  char t[20];
	  strcpy (t, fread_word (fp));
	  if (!str_cmp (t, "yes"))
	    c->clan = TRUE;
	  continue;
	}
      if (!str_cmp ("CLAN2", buf))
	{
	  char t[20];
	  strcpy (t, fread_word (fp));
	  if (!str_cmp (t, "yes"))
	    c->clan2 = TRUE;
	  continue;
	}
      if (!str_cmp ("COMMAND", buf))
	{
	  char cmd[40];
	  int i = 0;
	  strcpy (cmd, fread_word (fp));
	  while (c->commands[i])
	    i++;
	  c->commands[i] = str_dup (cmd);
	  continue;
	}
      if (!str_cmp ("COLOR", buf))
	{
	  c->color = str_dup (fread_word (fp));
	  continue;
	}
      if (!str_cmp ("ALIGNMENT", buf))
	{
	  char t[20];
	  strcpy (t, fread_word (fp));
	  if (!str_cmp ("both", t))
	    c->to_align = TO_BOTH;
	  if (!str_cmp ("evil", t))
	    c->to_align = TO_EVIL;
	  if (!str_cmp ("good", t))
	    c->to_align = TO_GOOD;
	  if (!str_cmp ("same", t))
	    c->to_align = SAME_ALIGN;
	  continue;
	}
      if (!str_cmp ("TO_LEVEL", buf))
	{
	  c->to_level = fread_number (fp);
	  continue;
	}
      fprintf (stderr, "Unknown read in channel.dat: %s\n", buf);
      fread_to_eol (fp);
    }

  fclose (fp);
  return;
}


void 
show_social (SOCIAL * s, CHAR_DATA * ch)
{
  char buf[500];
  int pp;
  pp = ch->position;
  ch->position = POSITION_STANDING;
  sprintf (buf, "Social \x1B[37;1mname\x1B[37;0m: %s\n\r", s->name);
  send_to_char (buf, ch);
  sprintf (buf, "\x1B[37;1mTo_char\x1B[37;0m w/no arg: %s\n\r", (s->char_no_arg ? s->char_no_arg : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "\x1B[37;1mTo_others\x1B[37;0m w/no arg: %s\n\r", (s->others_no_arg ? s->others_no_arg : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "To char when \x1B[37;1mChar_found\x1B[37;0m: %s\n\r", (s->char_found ? s->char_found : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "To \x1B[37;1mothers\x1B[37;0m when char found: %s\n\r", (s->others_found ? s->others_found : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "\x1B[37;1mTo_vict\x1B[37;0m when char found: %s\n\r", (s->vict_found ? s->vict_found : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "\x1B[37;1mChar_not\x1B[37;0m found: %s\n\r", (s->char_not_found ? s->char_not_found : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "\x1B[37;1mChar_self\x1B[37;0m specified (to char): %s\n\r", (s->char_auto ? s->char_auto : "none"));
  send_to_char (buf, ch);
  sprintf (buf, "\x1B[37;1mOthers_self\x1B[37;0m specified: %s\n\r", (s->others_auto ? s->others_auto : "none"));
  send_to_char (buf, ch);
  ch->position = POSITION_STANDING;
  return;
}