<?php

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


  /**
   * User class destructor
   ** Saves changes to the user 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);
  }


  /**
   * Returns all User Preferences
   * @param boolean $asJSON - Return results as a JSON string
   * @return array All currently saves session settings
   */
  public function getAll($asJSON = false)
  {
    return $asJSON ? json_encode(($this->_values ?? [])) : ($this->_values ?? []);
  }


  /**
   * Returns Filter Setting from Preference as Array
   * @param string $key
   * @return array Array of current filter settings, null if none.
   */
  public function getFilterSettingAsArray($key)
  {
    // Site Preferences that are arrays
    $filterSettings = [
      'livePacketViewFilter',
      'latestHeardFilter',
      'latestBeaconsFilter',
      'latestMessagesFilter',
      'latestStatusesFilter',
      'latestObjectsFilter',
      'latestInvalidFilter',
      'latestWeatherFilter',
      'movingStationsFilter'
    ];

    if (in_array($key, $filterSettings) && isset($this->$key) && !is_null($this->$key))
    {
      return array_map('intval', explode(',', $this->$key));
    }
    return null;
  }


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


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

    // Don't save unless the user ID has been sets
    if ($this->userId == null || $this->userId == 0)
    {
      $this->_lastError = 'No user ID has been set.';
      return false;
    }

    $sitePrefs = [
      'loginApplyMapCenterZoom'     => 'login_apply_map_center_zoom',
      'defaultMapCenterLatitude'    => 'default_map_center_latitude',
      'defaultMapCenterLongitude'   => 'default_map_center_longitude',
      'defaultMapZoom'              => 'default_map_zoom',
      'useImperialUnits'            => 'use_imperial_units',
      'useMilTime'                  => 'use_mil_time',
      'showStationaryMarkers'       => 'show_stationary_markers',
      'showInternetMarkers'         => 'show_internet_markers',
      'showAprsPositions'           => 'show_aprs_positions',
      'showCwopPositions'           => 'show_cwop_positions',
      'showOgnPositions'            => 'show_ogn_positions',
      'showCbAprsPositions'         => 'show_cb_aprs_positions',
      'showOgflymMarkers'           => 'show_ogflym_markers',
      'showUnknownMarkers'          => 'show_unknown_markers',
      'showStationMarkers'          => 'show_station_markers',
      'showObjectMarkers'           => 'show_object_markers',
      'showItemMarkers'             => 'show_item_markers',
      'showMaidenheadGrid'          => 'show_maidenhead_grid',
      'showDayNightOverlay'         => 'show_day_night_overlay',
      'dayNightRefreshInterval'     => 'day_night_refresh_interval',
      'applyMapSettingsAtLogin'     => 'apply_map_settings_at_login',
      'tailTimeLength'              => 'tail_time_length',


      'livePacketViewLimit'             => 'live_packet_view_limit',
      'livePacketViewFilter'            => 'live_packet_view_filter',

      'latestHeardLimit'                => 'latest_heard_limit',
      'latestHeardFilter'               => 'latest_heard_filter',
      'latestHeardAutoRefresh'          => 'latest_heard_auto_refresh',
      'latestHeardTableState'           => 'latest_heard_table_state',

      'latestBeaconsLimit'              => 'latest_beacons_limit',
      'latestBeaconsFilter'             => 'latest_beacons_filter',
      'latestBeaconsAutoRefresh'        => 'latest_beacons_auto_refresh',
      'latestBeaconsTableState'         => 'latest_beacons_table_state',

      'latestBulletinsLimit'            => 'latest_bulletins_limit',
      'latestBulletinsFilter'           => 'latest_bulletins_filter',
      'latestBulletinsAutoRefresh'      => 'latest_bulletins_auto_refresh',
      'latestBulletinsTableState'       => 'latest_bulletins_table_state',

      'latestMessagesLimit'             => 'latest_messages_limit',
      'latestMessagesFilter'            => 'latest_messages_filter',
      'latestMessagesAutoRefresh'       => 'latest_messages_auto_refresh',
      'latestMessagesTableState'        => 'latest_messages_table_state',

      'latestStatusesLimit'             => 'latest_statuses_limit',
      'latestStatusesFilter'            => 'latest_statuses_filter',
      'latestStatusesAutoRefresh'       => 'latest_statuses_auto_refresh',
      'latestStatusesTableState'        => 'latest_statuses_table_state',

      'latestObjectsLimit'              => 'latest_objects_limit',
      'latestObjectsFilter'             => 'latest_objects_filter',
      'latestObjectsAutoRefresh'        => 'latest_objects_auto_refresh',
      'latestObjectsTableState'         => 'latest_objects_table_state',

      'latestWeatherLimit'              => 'latest_weather_limit',
      'latestWeatherFilter'             => 'latest_weather_filter',
      'latestWeatherAutoRefresh'        => 'latest_weather_auto_refresh',
      'latestWeatherTableState'         => 'latest_weather_table_state',

      'latestInvalidLimit'              => 'latest_invalid_limit',
      'latestInvalidFilter'             => 'latest_invalid_filter',
      'latestInvalidAutoRefresh'        => 'latest_invalid_auto_refresh',
      'latestInvalidTableState'         => 'latest_invalid_table_state',

      'movingStationsLimit'             => 'moving_stations_limit',
      'movingStationsFilter'            => 'moving_stations_filter',
      'movingStationsAutoRefresh'       => 'moving_stations_auto_refresh',
      'movingStationsTableState'        => 'moving_stations_table_state',

      'stationBulletinsLimit'           => 'station_bulletins_limit',
      'stationBulletinsFilter'          => 'station_bulletins_filter',
      'stationBulletinsTableState'      => 'station_bulletins_table_state',

      'stationMessagesLimit'            => 'station_messages_limit',
      'stationMessagesTableState'       => 'station_messages_table_state',

      'stationWeatherTableState'        => 'station_weather_table_state',

      'stationNearbyTableState'         => 'station_nearby_table_state',
      'stationSenderTableState'         => 'station_sender_table_state',
      'stationReceiverTableState'       => 'station_receiver_table_state',

      'stationTelemetryValsTableState'  => 'station_telemetry_vals_table_state',
      'stationTelemetryBitsTableState'  => 'station_telemetry_bits_table_state',

      'aprstCheckinsTableState'         => 'aprst_checkins_table_state',
      'aprstStatsTableState'            => 'aprst_stats_table_state',
      'aprstLeaderboardTableState'      => 'aprst_leaderboard_table_state',

      'mpShowPath'                      => 'mp_show_path',
      'mpShowCourseSpeed'               => 'mp_show_course_speed',
      'mpShowMice'                      => 'mp_show_mice',
      'mpShowComment'                   => 'mp_show_comment',
      'mpShowPhgRng'                    => 'mp_show_phg_rng',
      'mpShowDistance'                  => 'mp_show_distance',
      'mpShowWeather'                   => 'mp_show_weather',
      'mpUseLargeIcon'                  => 'mp_use_large_icon',

      'useMaxModal'                     => 'use_max_modal',
      'currentWeatherDisplay'           => 'current_weather_display',

      'mapMarkerFontSize'                   => 'map_marker_font_size',
      'mapMarkerTextColor'                  => 'map_marker_text_color',
      'mapMarkerTextBackgroundColor'        => 'map_marker_text_background_color',
      'mapMarkerTextBackgroundTransparency' => 'map_marker_text_background_transparency',
      'showMapMarkerText'                   => 'show_map_marker_text',
      'dotMarkerSize'                       => 'dot_marker_size'
    ];

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

    // Inserting or saving?
    if ($this->isExistingObject())
    {
      $sql = 'UPDATE user_preferences SET ';
      $sqlParts = [];
      $parameters = [];

      // Add only the non-null preferences
      foreach ($sitePrefs AS $property => $column)
      {
        if (isset($this->$property))
        {
          array_push($sqlParts, "$column = ?");
          array_push($parameters, $this->$property);
        }
      }

      array_push($parameters, $this->_id);
      $sql .= implode(', ', $sqlParts);
      $sql .= 'WHERE id = ? LIMIT 1';

      $stmt = $pdo->prepareAndExec($sql, $parameters);
      if ($stmt)
      {
        $this->_isChanged = false;
        return true;
      }
      $this->_lastError = 'An error occurred saving the user preferences.';
    }
    else
    {
      $columns = ['user_id'];
      $parameters = [$this->userId];
      $placeholders = ['?'];

      // Add only the non-null preferences
      foreach ($sitePrefs AS $property => $column)
      {
        if (isset($this->$property))
        {
          array_push($columns, $column);
          array_push($placeholders, '?');
          array_push($parameters, $this->$property);
        }
      }

      $sql = "INSERT INTO user_preferences (" . implode(',', $columns) . ") VALUES (" . implode(',', $placeholders) . ")";

      $stmt = $pdo->prepareAndExec($sql, $parameters);
      $id = $pdo->lastInsertId();
      if ($id)
      {
        $this->_id = $id;
        $this->_isChanged = false;
        return true;
      }

      $this->_lastError = 'An error occurred creating the user preferences.';
    }

    return false;
  }


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


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