using Fiesta.Config;
using Fiesta.Players;
using Fiesta.Worlds;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Villain.Databases;
using World.Login;

using Console = Villain.Output.Console;

namespace World
{
	class Program
	{
		private static ServerInfo _serverInfo;
		private static ServerInfo.WorldServerInfo _worldServerInfo;

		private static DatabaseInfo _databaseInfo;

		private static ServerConfig _serverConfig;

		public static byte WorldID
		{
			get => _serverConfig.ID;
		}

		public static Fiesta.Worlds.World.WorldStatus WorldStatus
		{
			get
			{
				if (_serverConfig.Maintenance)
				{
					return Fiesta.Worlds.World.WorldStatus.Maintenance;
				}

				switch (PlayerManager.GetConnectionsCount())
				{
					case Int32 count when count > 1000:
						return Fiesta.Worlds.World.WorldStatus.High;
					
					case Int32 count when count > 100:
						return Fiesta.Worlds.World.WorldStatus.Medium;
				}

				return Fiesta.Worlds.World.WorldStatus.Low;
			}
		}

		static void Main(string[] args)
		{
			Console.Title = "World";

			try
			{
				Console.WriteLine("Loading...", ConsoleColor.Green);

				Load();

				Console.WriteLine("Starting...", ConsoleColor.Green);

				Start();

				Console.WriteLine("Server Started!", ConsoleColor.Green);
			}
			catch (Exception exception)
			{
				Console.WriteLine($"Server threw an exception with the message: {exception.Message}", ConsoleColor.Red);

				Shutdown();
			}

			while (true)
			{
				switch (Console.ReadLine())
				{
					case "shutdown":
						Shutdown();
						break;
				}
			}
		}

		public static void Load()
		{
#if DEBUG
			_serverInfo = ServerInfo.Load(@"D:\Projects\Fiesta\Visual Studio\Fiesta\Servers\Emulator\Data\Config\ServerInfo.json");
			_databaseInfo = DatabaseInfo.Load(@"D:\Projects\Fiesta\Visual Studio\Fiesta\Servers\Emulator\Data\Config\DatabaseInfo.json");

			_serverConfig = ServerConfig.Load(@"D:\Projects\Fiesta\Visual Studio\Fiesta\Servers\Emulator\Data\Config\World_Enid\Config.json");
#else
			_serverInfo = ServerInfo.Load(@"..\Data\Config\ServerInfo.json");
			_databaseInfo = DatabaseInfo.Load(@"..\Data\Config\DatabaseInfo.json");

			_serverConfig = ServerConfig.Load(@".\Config.json");
#endif
			
			_worldServerInfo = _serverInfo.Worlds.Find(x => x.ID == _serverConfig.ID);

			if (_worldServerInfo == null)
			{
				throw new Exception("Invalid World ID");
			}

			DatabaseManager.OnClosed = OnDatabaseClosed;

			if (_databaseInfo.ContainsKey($"World_{_worldServerInfo.Name}"))
			{
				DatabaseInfo.Info worldDatabaseInfo = _databaseInfo[$"World_{_worldServerInfo.Name}"];

				DatabaseManager.Add("World", new SQLServer(worldDatabaseInfo.Host, worldDatabaseInfo.Database, worldDatabaseInfo.Username, worldDatabaseInfo.Password));
			}
			else
			{
				throw new Exception($"Unable to read database info for \"World_{_worldServerInfo.Name}\"");
			}
			
			InterLoginManager.Load(_worldServerInfo.ID);
			PlayerManager.Load();
		}

		public static void Start()
		{
			InterLoginManager.Start(_serverInfo.Login);
			PlayerManager.Start(_worldServerInfo.Host, _worldServerInfo.Ports.Players);
		}

		public static void Shutdown()
		{
			try
			{
				InterLoginManager.Stop();
				PlayerManager.Stop();
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message, ConsoleColor.Yellow);
			}

			Console.WriteLine("Server has shut down. Press any key to exit...", ConsoleColor.Yellow);
			Console.ReadLine();

			Environment.Exit(0);
		}

		private static void OnDatabaseClosed(string id)
		{
			Console.WriteLine("Server has shut down. Press any key to exit...", ConsoleColor.Yellow);

			Shutdown();
		}
	}
}