using System.Net.Sockets;
using System.Collections.Generic;
using System.Threading;

namespace WorldOfPeacecraft
{
	public class Backend : IBackend
	{
		private Sender Send;
		private Receiver Rec;
		private Parser Parse;
		private TcpClient Client;
		private Dictionary<int, Dragon> Dragons;
		private Dictionary<int, Player> Players;
		private LinkedList<Message> ChatMessages;
		private Map Map;
        private Buffer SenderBuffer;
		private IGui Gui;
		private int SelfId;

		public Backend (IGui gui)
		{
			Gui = gui;
			Dragons = new Dictionary<int, Dragon> ();
			Players = new Dictionary<int, Player> ();
			ChatMessages = new LinkedList<Message> ();
			Client = new TcpClient ("localhost", 9999);
			Buffer receiverBuffer = new Buffer(10000);
			SenderBuffer = new Buffer(100);
			Parse = new Parser (this, receiverBuffer);
			Rec = new Receiver (Client, receiverBuffer);
			Send = new Sender (Client, SenderBuffer);
			SenderBuffer.AddLine ("get:map");
			SenderBuffer.AddLine ("get:me");
			SenderBuffer.AddLine ("get:ents");
		}

		public void SetSelfId (int id)
		{
			this.SelfId = id;
		}

		public IEnumerable<IEntity> GetDragons ()
		{
			return Dragons.Values;
		}

		public IEnumerable<IPlayer> GetPlayers ()
		{
			return Players.Values;
		}

		public void removeDragon (Dragon dragon)
		{
			Dragons.Remove (dragon.GetId ());
		}

		public void removePlayer (Player player)
		{
			Players.Remove (player.GetId ());
		}
		
		public void clearPlayers ()
		{
			Players.Clear ();
		}
		
		public void clearDragons ()
		{
			Dragons.Clear ();
		}

		public Player getPlayer (int playerId)
		{
			return Players[playerId];
		}

		public Dragon getDragon (int dragonId)
		{
			return Dragons[dragonId];
		}

		public Map getMapObject ()
		{
			return Map;
		}

		public void SetDragon (Dragon dragon)
		{
			Dragons [dragon.GetId ()] = dragon;
		}

		public void SetPlayer (Player player)
		{
			Players [player.GetId ()] = player;
		}

		public void SetMap (Map map)
		{
			this.Map = map;
		}

		public ITile[,] GetMap ()
		{
			if (Map == null) {
				return null;
			}
			return Map.GetTiles ();
		}

		public void AddChatMessage (Message message)
		{
			ChatMessages.AddLast (message);
		}

		public IEnumerable<IChatMessage> GetChatMessages ()
		{
			return ChatMessages;
		}

		public void SendCommand (string command)
		{
			SenderBuffer.AddLine (command);
		}

		public void SendChatMessage (string message)
		{
			SenderBuffer.AddLine ("ask:say:" + message);
		}

        public void moveUp()
        {
            SenderBuffer.AddLine("ask:mv:up");
        }

        public void moveDown()
        {
            SenderBuffer.AddLine("ask:mv:dwn");
        }
        public void moveLeft()
        {
            SenderBuffer.AddLine("ask:mv:lft");
        }
        public void moveRight()
        {
            SenderBuffer.AddLine("ask:mv:rgt");
        }

		public void MoveTo (int x, int y)
		{
			if (Map.GetTiles () [x, y].IsWalkable ()) {
				Thread thread = new Thread (() => WalkTo (x, y));
				thread.IsBackground = true;
				thread.Start ();
			}
		}

		private void WalkTo (int x, int y)
		{
			LinkedList<Coordinate> path = Pathfinder.FindPath (Players [SelfId].Coord, new Coordinate (x, y), Map);
			Pathwalker walker = new Pathwalker ();
			walker.SetCoords (path);
			while (walker.HasMoreSteps()) {
				SenderBuffer.AddLine("ask:" + walker.NextStep());
				Thread.Sleep(250);
			}
		}

		public void RefreshGui()
		{
			Gui.PerformRefresh();
		}

		public void StartThreads() {
			Parse.Start ();
			Rec.Start ();
			Send.Start ();
		}

		public void Stop() {
			Parse.Stop ();
			Send.Stop ();
			Client.Close ();
		}
	}
}

