using System;
using System.Timers;
using GTANetworkAPI;

/**
* @overview Life of German Reallife - WeatherSync
* @author Alex_qp
* @copyright (c) 2008 - 2021 Life of German
*/

namespace ReallifeGamemode.Server.World
{

  /// <summary>
  /// Serverwide WeatherSystem (+ sync)
  /// </summary>
  static class WeatherSync
  {
    // SETTINGS
    private const uint _syncInterval = 5 * 60 * 1000; // 5 min
    private static readonly int[] _countRange = new int[] { 3, 5 }; // min, max both inclusive. How often should weather be synced before actual changing? 

    // INTERNAL
    private static int _count = 0;
    private static int _targetCount = GetNewTargetCount();

    /// <summary>
    /// Get/Set the current weather.
    /// <remarks>Only use in main thread!</remarks>
    /// </summary>
    public static Weather Weather
    {
      get { return NAPI.World.GetWeather(); }
      set { NAPI.World.SetWeather(value); }
    }

    /// <summary>
    /// Set the current weather by string.
    /// </summary>
    /// <remarks>Only use in main thread!</remarks>
    /// </summary>
    /// <param name="weather"></param>
    public static void SetWeather(string weather)
    {
      NAPI.World.SetWeather(weather);
    }

    private static Timer weatherTimer;

    /// <summary>
    /// Loads/Starts the WeatherSync.
    /// </summary>
    public static void Load()
    {
      weatherTimer = new Timer(_syncInterval);
      weatherTimer.Start();
      weatherTimer.Elapsed += OnWeatherTimer;
      NAPI.Util.ConsoleOutput("Loaded WeatherSync");
    }

    private static int GetNewTargetCount()
    {
      return new Random().Next(_countRange[0], _countRange[1] + 1);
    }

    private static Weather GetRandomWeather(Weather[] weathers)
    {
      return weathers[new Random().Next(weathers.Length)];
    }

    private static void OnWeatherTimer(object sender, ElapsedEventArgs e)
    {
      NAPI.Task.Run(() =>
      {
        if (_count < _targetCount)
        {
          // sync weather for all players
          _count++;
          Weather = Weather;
        } 
        else
        {
          // change weather and reset counters
          _count = 0;
          _targetCount = GetNewTargetCount();
          Weather = Weather switch
          {
            Weather.EXTRASUNNY => GetRandomWeather(new Weather[] { Weather.EXTRASUNNY, Weather.CLEAR }),
            Weather.CLEAR => GetRandomWeather(new Weather[] { Weather.EXTRASUNNY, Weather.CLEAR, Weather.CLOUDS, Weather.SMOG }),
            Weather.CLOUDS => GetRandomWeather(new Weather[] { Weather.CLEAR, Weather.CLOUDS, Weather.SMOG, Weather.FOGGY, Weather.OVERCAST }),
            Weather.SMOG => GetRandomWeather(new Weather[] { Weather.CLOUDS, Weather.SMOG, Weather.FOGGY, Weather.OVERCAST }),
            Weather.FOGGY => GetRandomWeather(new Weather[] { Weather.CLOUDS, Weather.SMOG, Weather.FOGGY, Weather.OVERCAST, Weather.RAIN }),
            Weather.OVERCAST => GetRandomWeather(new Weather[] { Weather.CLOUDS, Weather.SMOG, Weather.RAIN, Weather.CLEARING }), // may add overcast
            Weather.RAIN => GetRandomWeather(new Weather[] { Weather.OVERCAST, Weather.RAIN, Weather.CLEARING, Weather.THUNDER }),
            Weather.THUNDER => GetRandomWeather(new Weather[] { Weather.RAIN, Weather.THUNDER, Weather.CLEARING }),
            Weather.CLEARING => GetRandomWeather(new Weather[] { Weather.CLEAR, Weather.CLOUDS, Weather.CLEARING }),
            _ => GetRandomWeather(new Weather[] { Weather.EXTRASUNNY, Weather.CLEAR }),
          };
        }
      });
    }
  }
}
