// Application includes
  require_once('lib/nusoap.php');

  // Files I have written for the interface.
  require_once('include/admin.php');
  require_once('include/psu.php');

  // Included from psu.php, not important here.
  if (!psu_init()) {
    echo 'Prima Supply Updater failed to initialize.';
    exit();
  }

  // Connecting to the database/loading our config.
  $link = psu_db_connect();
  $config = admin_load_config();

  // Create the server instance and register methods with the server
  $server = new soap_server;

  $server->register('authenticate');
  $server->register('sendRequestXML');
  $server->register('receiveResponseXML');
  $server->register('getLastError');
  $server->register('closeConnection');
  $server->register('connectionError');

  // Function code:  Each function logs its call and return..

  function authenticate($username, $password) {
    psulog('func_call authenticate: $username=' . $username . ', $password=', null, true);

    // To access all the global data as need be.
    global $config;
      
    // Generate ticket: unique for each session since it's salted with time()
    $retval[0] = md5(time() . $username);

    // Validate user... return either nvu or a filepath.
    // psu_valid_user checks against users in the database, included from psu.inc

    if (($uid = psu_valid_user($username, $password)) != false) {
      $retval[1] = stripslashes($config['filepath']);
      psu_session_start($uid, $retval[0]);
      $resmsg = 'Returned company filepath';
    }
    else {
      $retval[1] = 'nvu';
      $resmsg = 'Invalid username/password.';
    }

    psulog('func_return authenticate: token=' . $retval[0] . ', result=' . $resmsg, $uid, true);
    return $retval;
  }

  function sendRequestXML($ticket, $HCPResponse, $CompanyFileName, 
                          $qbXMLCountry, $qbXMLMajorVers, $qbXMLMinorVers) {

    // This block here loads the proper user based on the ticket and grabs the company they're with

    $uid = uid_from_ticket($ticket);
    if ($uid != false) {
      psu_session_update($ticket, 2);
      $company = company_from_uid($uid);
    }

    psulog('func_call sendRequestXML: ticket=' . $ticket . ', company=' . $company, $uid);

    // objXML is a class from the comments at PHP.net.  ^_^
    // qbxml is a class I wrote to create qbXML requests.
    global $objXML;
    global $qbxml;

    if ($company < 1) return '';    // Throw an error so we don't try updating with a non-existant company.

    /* 
     * $HCPResponse is only returned the first time, so we know there's a connection.
     * We'll take this opportunity to fill our action_queue based on the selected actions!
     */
    if ($HCPResponse != '') {
      // The file_write function is a wrapper I made just to output the XML to an HTML file.
      $output = $objXML->parse($HCPResponse);
      file_write('hcpresponse.html', $output);

      // This function adds new items, customers, and invoices to the queue which is then cycled through.
      populate_queue($company);
    }

    $message = array();
    $args = array();

    // Somewhat hacked loop at the moment-> grabs the next action from the queue.
    $again = true;
    while ($again === true) {
      $data = grab_next_action($company);
			
      if ($data != false && is_array($data)) {
        $message[] = $data['message'];
	$args[] = $data['args'];
	$again = $data['again'];
	if (!isset($rqid)) $rqid = $data['rqid'];
      }
      $again = false;
    }

    // the qbXML class returns valid qbXML requests based on what was in the queue..
    $retval = $qbxml->request($message, $args, $rqid);

    // Using my wrapper function to make this request into an HTML file for debug.		
    file_write('request' . $rqid . '.html', $retval);
  
    psulog(($retval == '') ? 'func_return sendRequestXML: (error)' : 'func_return sendRequestXML: qbXML', $uid);
    return $retval;
  }

  function receiveResponseXML($ticket, $response, $hresult, $message) {
    $psu_sd = psu_load_session($ticket);
    if ($psu_sd != false) {
      psu_session_update($ticket, 3);
      $uid = $psu_sd['user_id'];
      $company = company_from_uid($uid);
    }

    if ($hresult != '')
      psulog('func_call receiveResponseXML: ticket=' . $ticket . ', ERROR=' . $hresult . ', ' . $message, $uid);
    else
      psulog('func_call receiveResponseXML: ticket=' . $ticket . ", response: qbXML", $uid);

    global $objXML;

    // Parse the response.
    if ($response != '') {
      $output = $objXML->parse($response);
      file_write('responsexml.html', $output);
    }

    // Code to handle responses.
    if (isset($output[0]['children'][0]['children'])) {
      // This takes us to the level of the XML where responses are.
      $response = $output[0]['children'][0]['children'];
      // Cycle through the responses for each request sent.
      foreach($response as $action) {
        // This is a function call to keep track of how many actions a session performs.
        $counter = increment_action_count($ticket);
        $aid = $action['attrs']['REQUESTID'];
        // Do some error checking, log the results if need be.
	switch ($action['attrs']['STATUSCODE']) {
	  case 3100:
  	    $msg = "Attempted to import an item with a duplicate fullname.\n"
	         . $action['attrs']['STATUSMESSAGE'];
	    break;
	  case 3231:
 	    $msg = "The request was not processed due to a previous qbXML error.\n"
	         . $action['attrs']['STATUSMESSAGE'];
	    break;
	  default:
	    $msg = "Error " . $action['attrs']['STATUSCODE'] . ": " 
	         . $action['attrs']['STATUSMESSAGE'];
  	    break;
	}
        // Did it go through just fine?
	if ($action['attrs']['STATUSCODE'] == 0) {
	  // Update the action_state.
  	  update_action($aid, 3, true);
  	  switch ($action['name']) {
            // I truncated this for now just to show an example of what I do with responses
	    case 'CUSTOMERADDRS':
	      $custname = $action['children'][0]['children'][0]['tagData'];
	      $loc = strrpos($custname, '-');
              // Grab the customer's id number from the response..
	      $custid = substr($custname, $loc + 1);
						
	      // Drop it into the imported table
              
	      break;

              // Here is also where I handle things like saving settings.  Or for a TemplateQuery
              // I would write the returned available templates to the database for later usage.
  	  }
	}
	else {
	  update_action($aid, 4, true, $msg);
 	  psu_session_set_error($ticket, $msg);
        }
      }
    }

    // Calculate how many actions remain in the queue so I can return the correct % complete
    $left = actions_remaining($company);
    $total = $counter + $left;

    if ($total > 0)
      $retval = intval((($counter / $total) * 80) + 20);
    else
      $retval = 100;

    if ($retval <= 0)
      psulog('func_return receiveResponseXML: (error)', $uid);
    else 
      psulog('func_return receiveResponseXML: ' . $retval . '% complete', $uid);
    return $retval;
  }

  // Called when sendRequestXML returns an empty string or receiveResponseXML returns a negative value.
  function getLastError($ticket) {
    $uid = uid_from_ticket($ticket);
    if ($uid != false)
      psu_session_update($ticket, 4);

    psulog('func_call getLastError: ticket=' . $ticket, $uid);

    $retval = 'An error occurred... I know that for sure.';  // Return the appropriate error message.

    psulog('func_return getLastError: ' . $retval, $uid, true);
    return $retval;
  }

  function closeConnection($ticket) {
    // Close out the session in the database.
    $uid = uid_from_ticket($ticket);
    psu_session_end($ticket);

    psulog('func_call closeConnection: ticket=' . $ticket, $uid, true);

    // Return a final message describing our status here.
    $retval = 'Ticket ' . $ticket . ' closed, ' . actions_performed($ticket) . ' actions performed.';

    psulog('func_return closeConnection: ' . $retval, $uid, true);
    return $retval;
  }

  function connectionError($ticket, $hresult, $message) {
    $uid = uid_from_ticket($ticket);
    if ($uid != false)
      psu_session_update($ticket, 6);

    psulog('func_call connectionError: ticket=' . $ticket . ', ERROR=' . $hresult . ', ' . $message, $uid, true);

    $retval = 'done';  // Done indicates we can't go on, whereas we could try returning the company file path.

    psulog('func_return connectionError: Check to make sure your filepath is set properly', $uid);
    return $retval;
  }

  // Use the request to (try to) invoke the NuSOAP service
  $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
  $server->service($HTTP_RAW_POST_DATA);

  unset($server);
  psu_close();