using UnityEngine;
using System.Collections;
using System.IO;
using com.deeperbeige.lib;

// Do not use this yourself manually, it is set up automatically as required
// Used by the DevPanel class to provide dev panel functionality
namespace com.deeperbeige.lib.runtime
{
    public class DevPanelComponent : MonoBehaviour
    {
		public float       widthPercent { get; set; }
		public State       state        { get; set; }
		public bool        visible      { get; set; }
		public string      messages     { get; set; }
		public int         line         { get; set; }
		public GUIState    guiState     { get; set; }

		private float      pressedAt  = Mathf.Infinity;
		private int        cheatCount = 0;
		private GUIStyle   style      = null;
		private Texture2D  bgTexture         = null;

		public enum State
		{
			idle,
			touches,
			menu,
			open
		}
		
		public enum GUIState
		{
			root,
			report,
			wipe,
			cheats
		}

		public void Init()
		{
			widthPercent = 0.6f;
			visible      = false;
			line         = 0;
			messages     = "";
			state        = State.idle;
		}

		void OnGUI()
		{
			if (style == null)
			{
				bgTexture      = Resources.Load("Textures/GreenSkinBackground") as Texture2D;
				style          = new GUIStyle(GUI.skin.textArea);
				style.font     = Resources.Load("Fonts/Courier Prime") as Font;
				style.fontSize = 12;
				style.border   = new RectOffset(5, 5, 5, 5);
				style.padding  = new RectOffset(8, 8, 8, 8);
				
				// Crazy native GUI setup crap. What prat decided this was a good way to do GUI?
				GUI.contentColor                     = Colours.fromRGB(82, 236, 155);
				
				GUI.skin.textArea.normal.background  = bgTexture;
				GUI.skin.textArea.hover.background   = bgTexture;
				GUI.skin.textArea.focused.background = bgTexture;
				GUI.skin.textArea.active.background  = bgTexture;
				
				GUI.skin.button.normal.background    = bgTexture;
				GUI.skin.button.hover.background     = bgTexture;
				GUI.skin.button.focused.background   = bgTexture;
				GUI.skin.button.active.background    = bgTexture;
				
				GUI.skin.textArea.normal.textColor   = Colours.fromRGB(82, 236, 155);
				GUI.skin.textArea.hover.textColor    = Colours.fromRGB(82, 236, 155);
				GUI.skin.textArea.focused.textColor  = Colours.fromRGB(82, 236, 155);
				GUI.skin.textArea.active.textColor   = Colours.fromRGB(82, 236, 155);
			}
			
			if (! visible) return;
			
			// Standard menu button positions
			int width = Mathf.RoundToInt((float)Screen.width * widthPercent);
			int position0 = width     - 110;
			int position1 = position0 - 130;
			int position2 = position1 - 110;
			int position3 = position2 - 110;
			int position4 = position3 - 110;
			
			
			// Main log text area
			GUI.TextArea(new Rect(10, 10, width - 20, Screen.height - 90), messages, style);
			
			// Show close or back button
			if (guiState == GUIState.root)
			{
				if (GUI.Button(new Rect(position0, Screen.height - 70, 100, 50), "Close"))
				{
					visible     = false;
					state       = State.idle;
					pressedAt   = Mathf.Infinity;
					guiState    = GUIState.root;
					cheatCount  = 0;
				}
			} else {
				if (GUI.Button(new Rect(position0, Screen.height - 70, 100, 50), "Back"))
				{
					cheatCount = 0;
					guiState   = GUIState.root;
				}
			}
			
			switch (guiState)
			{
				case GUIState.root:
					
					// Sub-menus
					if (DevPanel.allowCheats && GUI.Button (new Rect(position3, Screen.height - 70, 100, 50), "Cheats...")) guiState = GUIState.cheats;
					if (GUI.Button (new Rect(position2, Screen.height - 70, 100, 50), "Reports..."))                        guiState = GUIState.report;
					if (GUI.Button (new Rect(position1, Screen.height - 70, 100, 50), "Reset..."))                          guiState = GUIState.wipe;
					break;
					
				case GUIState.report:
				
					// Levels report
					if (Levels.TotalLevels() > 0 && GUI.Button (new Rect(position4, Screen.height - 70, 100, 50), "Levels")) Levels.Report();
					
					// Device info
					if (GUI.Button (new Rect(position3, Screen.height - 70, 100, 50), "Device info"))
					{
						Resolution res = Screen.currentResolution;
						
						DevPanel.Log("Device:    " + SystemInfo.deviceModel);
						DevPanel.Log("OS:        " + SystemInfo.operatingSystem);
						DevPanel.Log("Screen:    " + res.width.ToString() + "x" + res.height.ToString() + " " + res.refreshRate + "Hz (" + ScreenSize.pixelsPerInch.ToString() + "dpi)");
						DevPanel.Log("Size:      " + ScreenSize.pixelsToCentimeters(res.width).ToString("0.0") + "cm x " + ScreenSize.pixelsToCentimeters(res.height).ToString("0.0") + "cm");
						DevPanel.Log("Language:  " + Application.systemLanguage);
						DevPanel.Log("Unique ID: " + SystemInfo.deviceUniqueIdentifier);
						DevPanel.Log("RAM:       " + SystemInfo.systemMemorySize + "Mb");
						DevPanel.Log("CPU:       " + SystemInfo.processorType);
						DevPanel.Log("Cores:     " + SystemInfo.processorCount);
						DevPanel.Log("GPU:       " + SystemInfo.graphicsDeviceName);
						DevPanel.Log("GPU make:  " + SystemInfo.graphicsDeviceVendor);
						DevPanel.Log("GPU RAM:   " + SystemInfo.graphicsMemorySize + "Mb");
						DevPanel.Log("Save path: " + Application.persistentDataPath);
					}
					
					// Sounds report
					if (GUI.Button (new Rect(position2, Screen.height - 70, 100, 50), "Sounds")) Sounds.ReportUsage();
					
					// Events report
					if (GUI.Button (new Rect(position1, Screen.height - 70, 100, 50), "Events")) Events.Report(true);
					
					break;
					
				case GUIState.wipe:
					
					// Clear dev panel
					if (GUI.Button (new Rect(position3, Screen.height - 70, 100, 50), "Clear"))
					{
						messages = "";
						
						cheatCount++;
						if (cheatCount == 10)
						{
							DevPanel.allowCheats = true;
							guiState = GUIState.cheats;
						}
					}
					
					// Wipe save files
					if (GUI.Button (new Rect(position2, Screen.height - 70, 100, 50), "Wipe save files"))
					{
						cheatCount = 0;
						DevPanel.DeleteAllSaveFiles();
					}
					
					// Wipe player prefs
					if (GUI.Button (new Rect(position1, Screen.height - 70, 100, 50), "Wipe prefs"))
					{
						DevPanel.Log("Wiping player prefs");
						cheatCount = 0;
						PlayerPrefs.DeleteAll();
						PlayerPrefs.Save();
					}
					break;
					
				case GUIState.cheats:
					
					// Unlock all levels
					if (Levels.TotalLevels() > 0 && GUI.Button (new Rect(position1, Screen.height - 70, 100, 50), "Unlock all\nlevels")) Levels.UnlockAll();
					break;
			}
		}
		
		private void Update()
		{
			switch (state)
			{
				case State.idle:
					if (Input.GetKey(KeyCode.Menu))
					{
						pressedAt = Time.time;
						state     = State.menu;
					}
					
					if (Input.touchCount == 4)
					{
						pressedAt = Time.time;
						state     = State.touches;
					}
					
					if (Input.GetKeyDown(KeyCode.Slash) && (Input.GetKey(KeyCode.RightControl) || Input.GetKey(KeyCode.LeftControl)))
					{
						pressedAt = Time.time - 3;
					}
					
					if (Input.GetKeyDown(KeyCode.Slash) && (Input.GetKey(KeyCode.RightControl) && Input.GetKey(KeyCode.RightShift)) && DevPanel.allowCheats)
					{
						visible  = true;
						state    = State.open;
						guiState = GUIState.cheats;
					}
					
					break;
					
				case State.touches:
					if (Input.touchCount < 4)
					{
						pressedAt = Mathf.Infinity;
						state     = State.idle;
					}
					
					break;
					
				case State.menu:
					if (! Input.GetKey(KeyCode.Menu))
					{
						pressedAt = Mathf.Infinity;
						state     = State.idle;
					}
					break;
					
				case State.open:
					if (Input.GetKeyDown(KeyCode.Menu) || Input.GetKeyDown(KeyCode.Escape))
					{
						visible = false;
						state   = State.idle;
					}
					break;
			}
			
			// Check for open
			if (Time.time > pressedAt + 2)
			{
				#if UNITY_ANDROID || UNITY_IPHONE || UNITY_BLACKBERRY || UNITY_WP8
				Handheld.Vibrate();
				#endif
				visible   = true;
				pressedAt = Mathf.Infinity;
				state     = State.open;
			}
		}
	}
}
