#region Arthea License
/***********************************************************************
*  Arthea MUD by R. Jennings (2007)      http://arthea.googlecode.com/ *
*  By using this code you comply with the Artistic and GPLv2 Licenses. *
***********************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
#if !MONO
using System.Runtime.Remoting.Channels.Tcp;
#endif
using Arthea.Connections;
using Arthea.Connections.Enums;
using Arthea.Connections.Players;
using Arthea.Environment;
namespace Arthea.Commands.Admin
{
    /// <summary>
    /// Implementation of a reboot command.
    /// </summary>
    public class RebootCommand : Command
    {
        #region [rgn] Constructors (1)
        /// <summary>
        /// Initializes a new instance of the <see cref="RebootCommand"/> class.
        /// </summary>
        public RebootCommand() : base("reboot", "reboots the game, keeping connections", Levels.Admin)
        {
        }
        #endregion [rgn]
        #region [rgn] Methods (1)
        // [rgn] Public Methods (1)
        /// <summary>
        /// Processes the command for a player.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="argument">The argument.</param>
        public override void Process(Player player, String argument)
        {
#if MONO
	        player.WriteLine("Reboot not available on this server.");
#else
            Log.Info("Reboot by {0}...", player.Name);
            player.Act(null, null, Act.ToWorld, "$n has initiated a reboot.");
            player.WriteLine("Reboot activated...");
            TcpChannel channel = new TcpChannel(RebootRecovery.Port);
            ChannelServices.RegisterChannel(channel, false); //register channel
            //register remote object
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof (RebootRecovery),
                "RebootRecovery",
                WellKnownObjectMode.SingleCall);
            System.Diagnostics.Process.Start(
                System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, "-reboot");
            while (!RebootRecovery.Done)
            {
            }
            ChannelServices.UnregisterChannel(channel);
            Server.Instance.State = ServerState.Stopping;
#endif
        }
        #endregion [rgn]
    }
    /// <summary>
    /// Implementation of a reboot recovery.
    /// </summary>
    public class RebootRecovery : MarshalByRefObject
    {
        #region [rgn] Fields (2)
        /// <summary>
        /// Signals this recovery is done
        /// </summary>
        public static bool Done = false;
        /// <summary>
        /// The port to use.
        /// </summary>
        public static int Port = 4010;
        #endregion [rgn]
        #region [rgn] Methods (2)
        // [rgn] Public Methods (2)
        /// <summary>
        /// Signales the recovery is done.
        /// </summary>
        public void Finished()
        {
            Done = true;
        }
        /// <summary>
        /// Transfers the connections.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns></returns>
        public Dictionary<string, SocketInformation> TransferConnections(int processId)
        {
            Log.Info("Transferring connections...");
            Dictionary<string, SocketInformation> connections =
                new Dictionary<string, SocketInformation>();
            foreach (Connection con in Lists.Connections)
            {
                if (con.State != ConnectionState.Playing)
                {
                    continue;
                }
                connections.Add(con.Player.Name, con.Socket.DuplicateAndClose(processId));
            }
            return connections;
        }
        #endregion [rgn]
    }
}