<?php

class QRZ
{
  private                 $_localSessionData = [];
  private                 $_apiURL = '';
  public    string        $_lastError = '';

  public function __construct()
  {
    // Initialize stuff
    $this->_init();
  }


  public function __destruct()
  {
    $this->_localSessionData = array();
  }


  /**
   * Sets the $value for a $key
   *
   * @param string $key (Name of the paramter to set)
   * @param mixed $value (Value of the paramter to set)
   */
  public function __set($key, $value)
  {
    $this->_localSessionData[$key] = $value;
  }


  /**
   * Returns the $value for a $key
   *
   * @param string $key (Name of the paramter to retreive)
   * @return mixed $value (Value associated with $key)
   */
  public function __get($key)
  {
    return $this->_localSessionData[$key] ?? null;
  }


  /**
   * Checks is a session varianle is set.
   */
  public function __isset($key)
  {
    return isset($this->_localSessionData[$key]);
  }


  /**
   * Initialize the QRZ class
   * This is called for every page request
   * sets _lastError to an empty string.
   */
  private function _init()
  {
    $this->_apiURL  = getConfig('qrz', 'api_url');
    $this->username = getConfig('qrz', 'username');
    $this->password = getConfig('qrz', 'password');
    $this->_lastError = '';

    // Get the site backend database connection
    $pdo = PDOMysqlConnection::getInstance();

    // Get the QRZ config
    $sql = "SELECT value FROM config WHERE name='qrz_key'";
    $stmt = $pdo->prepareAndExec($sql);
    if ($stmt) $this->sessionKey = $stmt->fetchColumn();
  }


  /**
   * Saves QRZ config
   * This is called for every page request
   * sets _lastError to an empty string.
   */
  private function _save()
  {
    // Get the site backend database connection
    $pdo = PDOMysqlConnection::getInstance();

    // Get the QRZ config
    $sql = "UPDATE config SET value = ? WHERE name='qrz_key'";
    $stmt = $pdo->prepareAndExec($sql, [$this->sessionKey]);
  }


  /**
   * Starts a QRZ user session
   *
   * @return boolean (True if session key is returned)
   */
  public function qrzLogin()
  {
    $uriStub = "?username={$this->username};password={$this->password};agent=n2rwe2.0";

    $xmlResponse = simplexml_load_string(file_get_contents($this->_apiURL . $uriStub));
    if ($xmlResponse && isset($xmlResponse->Session))
    {
      if ($xmlResponse->Session->Key)
      {
        $this->sessionKey = $xmlResponse->Session->Key[0];
        $this->queryCount = $xmlResponse->Session->Count[0];
        $this->_save();
        return true;
      }
      else
      {
        $this->_lastError = 'Could not obtain a session token from QRZ.com';
      }
    }
    else
    {
      $this->_lastError = 'Communication error with QRZ.com';
    }

    return false;
  }


  /**
   * Query a QRZ callsign
   *
   * @return boolean (True if session key is returned)
   */
  public function queryCall($callsign)
  {
    $callsign = strtoupper(trim($callsign ?? ''));
    if (strlen($callsign) == 0)
    {
      $this->_lastError = 'No callsign specified.';
      return false;
    }

    // Query the callsign
    $uriStub = "?s={$this->sessionKey};callsign={$callsign}";

    $xmlResponse = simplexml_load_string(file_get_contents($this->_apiURL . $uriStub));

    // Check the response for the session key being returned
    if ($xmlResponse && (!isset($xmlResponse->Session) || !isset($xmlResponse->Session->Key)))
    {
      // Relogin required
      if (!$this->qrzLogin())
      {
        // Login failed
        return false;
      }

      // Re-attempt the query
      $xmlResponse = simplexml_load_string(file_get_contents($this->_apiURL . $uriStub));
    }

    // By this point we should have a callsign record returned
    if ($xmlResponse && $xmlResponse->Callsign)
    {
      if (strtoupper($xmlResponse->Callsign[0]->call[0]) == $callsign)
      {
        $this->Callsign = $xmlResponse->Callsign[0];
        return true;
      }
      else
      {
        $this->_lastError = 'Could not find user at QRZ.com';
      }
    }
    else
    {
      $this->_lastError = 'Communication error with QRZ.com';
    }

    return false;
  }


  /**
   * Returns all Session Values
   * @return array All currently saves session settings
   */
  public function getAll()
  {
    return $this->_localSessionData ?? [];
  }


  /**
   * Returns the last error message set during a session action then
   * sets _lastError to an empty string.
   *
   * @return string (Text of the last recorded error)
   */
  public function getLastError()
  {
    $last_error = $this->_lastError;
    $this->_lastError = '';
    return $last_error;
  }
}
