<?php

class PersonalAPI extends Model
{
  private bool $_isChanged = false;
  private bool $_autoSave = true;
  private string $_lastError = '';

  public function __construct($id)
  {
    parent::__construct($id);

    // Critical properties
    $this->_isChanged = false;
  }


  /**
   * PersonalAPI class destructor
   ** Saves changes to the station favorite record if there are any (and autoSave is not disabled)
   */
  public function __destruct()
  {
    if ($this->_autoSave && $this->_isChanged) $this->save();
  }


  /**
   * Makes it possible to set $object->field
   *
   * @param string $key
   * @param mixed
   */
  public function __set($key, $value)
  {
    $this->_isChanged = true;
    parent::__set($key, $value);
  }


  /**
   * Clone the object set the isChanged flag
   *
   */
  public function __clone()
  {
    $this->_isChanged = true;
    $this->_id = 0;
  }


  /**
   * Enables the API
   */
  public function enable()
  {
    $this->enabled = true;
  }


  /**
   * Disables the API
   */
  public function disable()
  {
    $this->enabled = false;
  }


  /**
   * Set AutoSave
   ** Allows (or prevents) changes to the PersonalAPI record from being saved to the database at
   ** completion of script execution.  Enabled by default.
   *
   * @param string $autoSave (True if changes are to be saved automatically, otherwise false)
   */
  public function setAutoSave($autoSave)
  {
    $this->_autoSave = $autoSave;
  }


  /**
   * Generate an unique personal API key
   */
  public function generateKey()
  {
    // Geneate a 20 character token
    $this->apiKey = generateSecureToken(10);
  }

  /**
   * Increments the usage counter
   */
  public function incrementCounter()
  {
    // Geneate a 20 character token
    $this->count++;
  }


  /**
   * Save the PersonalAPI record if there are any changes pending
   *
   * @return boolean (True if save was successful, otherwise false)
   */
  public function save()
  {
    // Don't save unless something has been changed
    if ($this->_isChanged === false)
    {
      $this->_lastError = 'No changes have been made to save.';
      return false;
    }

    // Generate the key if not already set
    if (!isset($this->apiKey))
    {
      $this->generateKey();
    }

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

    // Inserting or saving?
    if ($this->isExistingObject())
    {
      $sql =
        'UPDATE personal_api
          SET
              user_id = ?, api_key = ?, enabled = ?, count = ?
          WHERE id = ?
          LIMIT 1';
      $stmt = $pdo->prepareAndExec($sql,
        [
          $this->userId,
          $this->apiKey,
          $this->enabled,
          $this->count,
          $this->_id
        ]);
      if ($stmt)
      {
        $this->_isChanged = false;
        return true;
      }
      $this->_lastError = 'An error occurred saving the Personal API record.';
    }
    else
    {
      $sql =
        'INSERT INTO personal_api
          (
           user_id, api_key, enabled
          )
          VALUES (?, ?, ?)';

      $stmt = $pdo->prepareAndExec($sql,
        [
          $this->userId, $this->apiKey, $this->enabled
        ]);
      $id = $pdo->lastInsertId();
      if ($id)
      {
        $this->_id = $id;
        $this->_isChanged = false;
        return true;
      }

      $this->_lastError = 'An error occurred creating Personal API record.';
    }

    return false;
  }


  /**
   * Delete the PersonalAPI record
   *
   * @return boolean (True if delete was successful, otherwise false)
   */
  public function delete()
  {
    if ($this->isExistingObject())
    {
      // Get the site backend database connection
      $pdo = PDOMysqlConnection::getInstance();

      $sql = 'DELETE FROM personal_api WHERE id = ? LIMIT 1';
      $stmt = $pdo->prepareAndExec($sql, [$this->_id]);
      if ($stmt)
      {
        return true;
      }
      $this->_lastError = 'An error occurred deleting the Personal API record.';
    }
  }


  /**
   * Returns the last error message set during a user 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;
  }
}
