// Copyright © 2017-2018 Atomic Software, LLC. All Rights Reserved.
// See LICENSE.md for full license information.

using Atom.Core;
using Atom.Core.Diagnostics;
using Atom.Core.Extensions;
using Atom.Core.Local;
using Atom.Core.Networking;
using Atom.Core.Networking.Messages.Structures.Local;
using Atom.Core.Networking.Messages.Structures.User;
using Atom.LoginServer.Services;
using System.Linq;

namespace Atom.LoginServer.Logic
{
    internal static class WMLogic
    {
        internal static void RegisterWorld(Client client, byte number, string name, string ip, int port)
        {
            if (WMService.Worlds.Exists(x => x.Client == client || x.Number == number))
            {
                new PROTO_NC_LOCAL_REGISTERWORLD_ACK(false).SendLocal(client);
                return;
            }

            WMService.RegisterWorld(client, number, name, ip, port);
            new PROTO_NC_LOCAL_REGISTERWORLD_ACK(true).SendLocal(client);

            Log.Info($"Registered world [{number}]");
        }

        internal static void SelectWorld(Client client, byte worldNo)
        {
            var SelectedWorld = WMService.Worlds.FirstOrDefault(x => x.Number == worldNo);

            if (SelectedWorld == null)
            {
                Log.Warning($"{client.Account.Username} tried to join an invalid world");
                new PROTO_NC_USER_LOGINFAIL_ACK(LoginFailedErrorCode.Maintenance).Send(client);
                return;
            }

            switch (SelectedWorld.Status)
            {
                case WorldStatus.Maintenance:
                    Log.Warning($"{client.Account.Username} tried to join world in maintenance");
                    new PROTO_NC_USER_LOGINFAIL_ACK(LoginFailedErrorCode.Maintenance).Send(client);
                    return;
                case WorldStatus.Offline:
                case WorldStatus.OfflineUnk:
                case WorldStatus.Reserved:
                    Log.Warning($"{client.Account.Username} tried to join an offline world");
                    new PROTO_NC_USER_LOGINFAIL_ACK(LoginFailedErrorCode.Maintenance).Send(client);
                    return;
                default:
                    Log.Info($"{client.Account.Username} joined world {SelectedWorld.Name}");
                    break;
            }

            TransferService.TransferClientToWM(client, SelectedWorld);
        }
    }
}
