<?php

class Mapshot 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;
  }


  /**
   * Mapshot class destructor
   ** Saves changes to the mapshot 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 by erasing the unique ID, user ID, and set the isChanged flag
   *
   */
  public function __clone()
  {
    $this->_isChanged = true;
    $this->_id = 0;
    $this->userId = 0;
  }


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


  /**
   * Set AutoSave
   ** Allows (or prevents) changes to the Mapshot 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;
  }


  /**
   * Sets the mapshot name.
   ** Ensures it has a minimum 4 characters in length,
   ** and a maximum of 40 characters in length
   *
   * @param string $name
   * @return boolean (True if name is acceptable and was set, otherwise false)
   */
  public function setName($name)
  {
    // Remove whitespace
    $name = trim($name);

    // Test the name and set it if passes
    if ((strlen($name) >= 4 || strlen($name) <= 50) && preg_match('/[^a-z_\-0-9]/i', $name) == 0)
    {
        $this->mapshotName = $name;
        $this->_isChanged = true;
        return true;
    }
    else
    {
      $this->_lastError = 'Mapshot name is too short or contains invalid characters. Acceptable characters A-Z, a-z, 0-9, underscore(_), hyphen(-).';
    }
    return false;
  }


  /**
   * Sets the optional mapshot description.
   ** Ensures it has a maximum length of 500 characters in length,
   ** and contains no invalid characters
   *
   * @param string $name
   * @return boolean (True if name is acceptable and was set, otherwise false)
   */
  public function setDescription($description)
  {
    // Remove whitespace
    $name = strip_tags(trim($description));

    // Test the name and set it if passes
    if (strlen($description) <= 500)
    {
        $this->mapshotDescription = $description;
        $this->_isChanged = true;
        return true;
    }
    else
    {
      $this->_lastError = 'Mapshot description is too long.  Must be less than 500 characters.';
    }
    return false;
  }


  /**
   * Save the Mapshot 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;
    }

    // Make sure all critical properties are completed
    if ( is_null($this->userId) || is_null($this->mapshotName)
      || is_null($this->mapCenterLatitude) || is_null($this->mapCenterLongitude) || is_null($this->mapZoom)
      || is_null($this->showStationaryMarkers) || is_null($this->showInternetMarkers) || is_null($this->showAprsPositions)
      || is_null($this->showCwopPositions) || is_null($this->showOgnPositions) || is_null($this->showCbAprsPositions)
      || is_null($this->showOgflymMarkers) || is_null($this->showUnknownMarkers)
      || is_null($this->showStationMarkers) || is_null($this->showObjectMarkers) || is_null($this->showItemMarkers)
      || is_null($this->showMaidenheadGrid)
      || is_null($this->showDayNightOverlay) || is_null($this->dayNightRefreshInterval) || is_null($this->tailTimeLength)
      || is_null($this->timeTravelDate) || is_null($this->trackStationId) || is_null($this->filterStationIds)
      || is_null($this->filterVisibleSymbols) || is_null($this->filterSymbolInvert) || is_null($this->filterAltitude)
      || is_null($this->filterAttrWx) || is_null($this->filterAttrTelem))
    {
      $this->_lastError = 'Cannot save, one or more mapshot settings are missing.';
      return false;
    }

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

    // Inserting or saving?
    if ($this->isExistingObject())
    {
      $sql =
        'UPDATE mapshots
          SET
              is_shared = ?,
              map_center_latitude = ?, map_center_longitude = ?, map_zoom = ?,
              show_stationary_markers = ?, show_internet_markers = ?, show_aprs_positions = ?,
              show_cwop_positions = ?, show_ogn_positions = ?, show_cb_aprs_positions = ?,
              show_ogflym_markers = ?, show_unknown_markers = ?,
              show_station_markers = ?, show_object_markers = ?, show_item_markers = ?,
              show_maidenhead_grid = ?,
              show_day_night_overlay = ?, day_night_refresh_interval = ?, tail_time_length = ?,
              time_travel_date = FROM_UNIXTIME(?), track_station_id = ?, filter_station_ids = ?,
              filter_visible_symbols = ?, filter_symbol_invert = ?, filter_speed = ?, filter_altitude = ?,
              mapshot_name = ?, mapshot_description = ?, mapshot_icon = ?,
              filter_attr_wx = ?, filter_attr_telem = ?
          WHERE id = ?
          LIMIT 1';
      $stmt = $pdo->prepareAndExec($sql,
        [
          $this->isShared,
          $this->mapCenterLatitude, $this->mapCenterLongitude, $this->mapZoom,
          $this->showStationaryMarkers, $this->showInternetMarkers, $this->showAprsPositions,
          $this->showCwopPositions, $this->showOgnPositions, $this->showCbAprsPositions,
          $this->showOgflymMarkers, $this->showUnknownMarkers,
          $this->showStationMarkers, $this->showObjectMarkers, $this->showItemMarkers,
          $this->showMaidenheadGrid,
          $this->showDayNightOverlay, $this->dayNightRefreshInterval, $this->tailTimeLength,
          $this->timeTravelDate, $this->trackStationId, $this->filterStationIds,
          $this->filterVisibleSymbols, $this->filterSymbolInvert, $this->filterSpeed,
          $this->filterAltitude, $this->mapshotName, $this->mapshotDescription, $this->mapshotIcon,
          $this->filterAttrWx, $this->filterAttrTelem,
          $this->_id
        ]);
      if ($stmt)
      {
        $this->_isChanged = false;
        return true;
      }
      $this->_lastError = 'An error occurred saving the mapshot record.';
    }
    else
    {
      $sql =
        'INSERT INTO mapshots
          (is_shared,
           user_id, map_center_latitude, map_center_longitude, map_zoom,
           show_stationary_markers, show_internet_markers, show_aprs_positions,
           show_cwop_positions, show_ogn_positions, show_cb_aprs_positions,
           show_ogflym_markers, show_unknown_markers,
           show_station_markers, show_object_markers, show_item_markers,
           show_maidenhead_grid,
           show_day_night_overlay, day_night_refresh_interval, tail_time_length,
           time_travel_date, track_station_id, filter_station_ids,
           filter_visible_symbols, filter_symbol_invert, filter_speed, filter_altitude,
           mapshot_name, mapshot_description, mapshot_icon,
           filter_attr_wx, filter_attr_telem)
          VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, FROM_UNIXTIME(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';

      $stmt = $pdo->prepareAndExec($sql,
        [
          $this->isShared,
          $this->userId, $this->mapCenterLatitude, $this->mapCenterLongitude, $this->mapZoom,
          $this->showStationaryMarkers, $this->showInternetMarkers, $this->showAprsPositions,
          $this->showCwopPositions, $this->showOgnPositions, $this->showCbAprsPositions,
          $this->showOgflymMarkers, $this->showUnknownMarkers,
          $this->showStationMarkers, $this->showObjectMarkers, $this->showItemMarkers,
          $this->showMaidenheadGrid,
          $this->showDayNightOverlay, $this->dayNightRefreshInterval, $this->tailTimeLength,
          $this->timeTravelDate, $this->trackStationId, $this->filterStationIds,
          $this->filterVisibleSymbols, $this->filterSymbolInvert, $this->filterSpeed,
          $this->filterAltitude, $this->mapshotName, $this->mapshotDescription,
          $this->mapshotIcon, $this->filterAttrWx, $this->filterAttrTelem
        ]);
      $id = $pdo->lastInsertId();
      if ($id)
      {
        $this->_id = $id;
        $this->_isChanged = false;
        return true;
      }

      $this->_lastError = 'An error occurred creating the mapshot record.';
    }

    return false;
  }


  /**
   * Delete the Mapshot 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 mapshots WHERE id = ? LIMIT 1';
      $stmt = $pdo->prepareAndExec($sql, [$this->_id]);
      if ($stmt)
      {
        return true;
      }
      $this->_lastError = 'An error occurred deleting the mapshot 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;
  }
}
