<?
class socket {
	var $address = "0.0.0.0";
	var $port    = 4000;
	var $client  = array();
	var $read    = array();
	var $listen_fd;
	var $nready;

	function socket( $address, $port )
	{
		set_time_limit(0); 
                ob_implicit_flush();
		$this->address = $address;
		$this->port = $port;
		$this->socket_init();
	}

	function resetconnection ( $desc, $indx ) 
	{
		remove_player( $indx );
		$this->client[$indx] = NULL;
		echo "Just dropped : $desc with an index of $indx\n";
                $this->read[$indx] = NULL;
                $this->close( $desc );
        }


	function socket_init()
	{
		if( ( $this->listen_fd = socket_create(AF_INET, SOCK_STREAM, 0) ) < 0 )
		{
			echo "socket_create() failed: reason: " . socket_strerror ($ret) . "\n";
			exit;
		}
		
		socket_setopt( $this->listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);

		if( ( $ret = socket_bind($this->listen_fd, $this->address, $this->port)) < 0 )
		{
			echo "socket_bind() failed: reason: " . socket_strerror ($ret) . "\n";
			$this->close( $this->listen_fd );
			exit;
		}

		if( ( $ret = socket_listen( $this->listen_fd ) ) < 0 )
		{
			echo "socket_listen() failed: reason: " . socket_strerror ($ret) . "\n";
			exit;
		}
	echo "Scratch mud up and running at: $this->address:$this->port\n";
	}
	
	function close( $sock )
	{
		socket_close( $sock );
	}

	function first_time ( $desc, $indx )
	{
		if ( !$this->client[$indx]["already_playing"] )
		{
			return true;
		}
		else if ( empty( $desc ) )
		{
			$this->resetconnection( $desc, $indx );
			return false;
		}
		else
			return false;

	}

	function show_header ( $desc, $indx, $n )
	{
		if( empty( $n ) || strlen( $n ) < 5 )
		{
			send_to_desc( $desc, "You're name must be greater than 5 characters\n" );
			send_to_desc( $desc, "What is your name?: ");
			$input = trim(socket_read($desc, 1024));
			$this->show_header( $desc, $indx, $input );
		}
		else if ( $desc ) 
		{
			$player 	 = new Player;
			$player->name    = $n;
			$player->prompt  = " bar>";
			$player->sock_id = $desc;
			$player->con	 = CON_CONNECTING;

			/* add the player to the world char_list array for quick global reference */
			add_player( $indx, $player );
                        socket_getpeername ($desc, $peer_addr, $peer_port);
                        game_log( " Connection from $peer_addr\n\r" );
			bust_a_prompt( $player );
                	$this->client[$indx]["already_playing"] = true;
		}
		else
		{
			$this->resetconnection( $desc, $indx );
			game_log( "[Bug] => resetting connection for $desc with index of => $indx\n");
		}
        }
	
	function recv()
	{
		global $char_list;

		for( $i = 0; $i < MAX_CLIENTS; $i++ )
    		{
			$desc = $this->client[$i][0];

        		if ( in_array( $desc, $this->read ) )
        		{
				  //There has to be a better way to check for closing sockets
				  if( ( $ret = @socket_getpeername ($desc, $peer_addr, $peer_port) ) <= 0 )
                        	  {
                                	$this->resetconnection( $desc, $i );
                                	break;
                        	  }

				  $n = trim(socket_read($desc, 1024));

				  if( $this->first_time( $desc, $i ) )
				  {
					$this->show_header( $desc, $i, $n );
					break;
				  }

            			  if ($n)
            			  {
					$tokens = array();

					$raw_tokens = explode (' ', trim ($n));
                			//the first one is the command
                			$command = $raw_tokens[0];

					if( ( $ret_arr = check_command( $command ) ) > 0 )
					{
                                        	$params = array_slice ($raw_tokens, 1);
                                        	//store them to pass them to the command parser

						$ret_command = $ret_arr[0];
						//It'll be better to move this to it's own wrapper
					        //for a more detailed command parser
						$ret_command( $char_list[$i], $params );
					}
					else
					{
						socket_write($desc, "Huh? [ $command ]\n");
					}
				   bust_a_prompt( $char_list[$i] );
                                   }
        		}
    		}
	}

	function accept_new_connection()
	{
		global $char_list;

		$this->read[0] = $this->listen_fd;
		// these next lines set up our clients and our
    		// listener socket for reading...   

		for( $i = 0; $i < MAX_CLIENTS; $i++ )
		{
			/* If they are already connected, put them back in
			 * the read[] array since we just wiped it
			 */
			if( $this->client[$i][0] != NULL )
			{
				$this->read[$i + 1] = $this->client[$i][0];
			}

		}

    		// now a blocking call to socket_select(). This will
    		// wait forever until a connection is received.
    		$nready = socket_select( $this->read, $null, $null, null);

		// if a new connection is being made, accept it and
    		// put it into the client array...
    		if ( in_array( $this->listen_fd, $this->read) )
    		{
        		for ($i = 0; $i < MAX_CLIENTS; $i++)
        		{
            			if ($this->client[$i][0] == null)
            			{
                			$this->client[$i][0] = socket_accept( $this->listen_fd );
					if ( !$this->client[$i]["already_playing"] )
                                	{
						socket_write($this->client[$i][0], "This is the welcome, enter name: ");
                                	}
					//socket already established but closed
					break;
            			}
            			else if ($i == MAX_CLIENTS - 1)
                			trigger_error("too many clients", E_USER_ERROR);
				if (--$nready <= 0)
				{
            				continue;
				}
        		} 
    		}
	}

};