using System;
using System.Collections;
using DotNetMock;

namespace DotNetMock.Examples.Mainframe
{
	public class MockMainframeConnection : IMainframeConnection
	{
		private ExpectationCounter _connectCalls = new ExpectationCounter("MockMainframeConnection.ConnectCalls");
		private ExpectationCounter _disconnectCalls = new ExpectationCounter("MockMainframeConnection.DisconnectCalls");
		private ExpectationCounter _sendKeyCalls = new ExpectationCounter("MockMainframeConnection.SendCalls");
		private ExpectationValue _keyPress = new ExpectationValue("MockMainframeConnection.KeyPress");

		private Hashtable _screens = null;
		private string[,] _currentScreen = null;

		public MockMainframeConnection() {
			_screens = new Hashtable();
		}
		public void CreateScreen(string screenName, string[,] screen)
		{
			foreach (string key in _screens.Keys)
			{
				if (key.Equals(screenName)) 
				{
					throw new ApplicationException("Cannot add duplicate screen: " + screenName);
				}
			}
			_screens.Add(screenName, screen);
		}
		public void SetField(string screenName, int row, int column, string message)
		{
			string[,] screen = (string[,])_screens[screenName];
			if (screen == null) 
			{
				throw new ApplicationException("No valid screen setup for that screen name: " + screenName);
			}
			char[ ]messageArray = message.ToCharArray();
			int currentColumn = column - 1;
			int currentRow = row - 1;
			for (int i = 0; i < messageArray.Length; i++) 
			{
				screen[currentRow, currentColumn] = messageArray[i].ToString();
				currentColumn++;
			}
		}

		public void SetExpectedConnectCalls(int calls) 
		{
			_connectCalls.Expected = calls;
		}
		public void SetExpectedDisconnectCalls(int calls) 
		{
			_disconnectCalls.Expected = calls;
		}
		public void SetExpectedKeyPress(MainframeConnection.Keys key)
		{
			_keyPress.Expected = key;			
		}
		public void SetExpectedSendKeyCalls(int calls) 
		{
			_sendKeyCalls.Expected = calls;
		}
		#region IMainframeConnection Implementation
		public void Connect(string sessionID) 
		{
			_connectCalls.Inc();
		}
		public void SetScreen(string screenName)
		{
			bool found = false;
			foreach (string key in _screens.Keys)
			{
				if (key.Equals(screenName))
				{
					found = true;
				}
			}
			if (!found) 
			{
				throw new ApplicationException("A screen named " + screenName + " has not been setup");
			}
			_currentScreen = (string[,])_screens[screenName];	
		}
		public void PutField(int row, int column, string message, int length)
		{
			char[ ]messageArray = message.ToCharArray();
			int currentColumn = column - 1;
			int currentRow = row - 1;
			for (int i = 0; i < messageArray.Length; i++) 
			{
				_currentScreen[currentRow, currentColumn] = messageArray[i].ToString();
				currentColumn++;
			}
		}
		public string GetField(int row, int column, int length)
		{
			string output = "";
			int currentRow = row - 1;
			int currentColumn = column - 1;
			int currentLength = length;
			int i = 0;
			try 
			{
				for (i = 1; i <= currentLength; i++)
				{
					output += _currentScreen[currentRow,currentColumn];
					currentColumn++;
				}
			}
			catch (System.Exception ex)
			{
				throw new System.Exception("Current Row: " + currentRow.ToString() + "  Current Column: " + currentColumn.ToString() + "   Current Length: " + currentLength.ToString() + " I: " + i.ToString() + Environment.NewLine + "Exception Message: " + ex.Message);
			}
			return output;	
		}
		public void SendKey(MainframeConnection.Keys key)
		{
			_sendKeyCalls.Inc();
			_keyPress.Actual = key;
		}
		public void Wait() 
		{
		}
		public void Disconnect()
		{
			_disconnectCalls.Inc();
		}
		#endregion
	}
}
