using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Media;

namespace pcd_g1
{
	partial class MainForm : Form
	{
		public static MainForm form = null;

		public enum KEYBOARD
		{
			Up = 1, Right = 2, Left = 4, Down = 8, Z = 16, X = 32
		}

		const int SCREEN_WIDTH = 640;
		const int SCREEN_HEIGHT = 480;

		public MainForm()
		{
			InitializeComponent();
			form = this;
		}

		Keys KEY_UP, KEY_DN, KEY_R, KEY_L, KEY_Z, KEY_X;
		private void LoadKey()
		{
			string fname = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + "\\key.setting";
			if (System.IO.File.Exists(fname))
			{
				var reader = new System.IO.StreamReader(fname);
				try
				{
					string s = reader.ReadLine();
					int i = int.Parse(s);
					KEY_UP = (Keys)i;
					KEY_DN = (Keys)int.Parse(reader.ReadLine());
					KEY_L = (Keys)int.Parse(reader.ReadLine());
					KEY_R = (Keys)int.Parse(reader.ReadLine());
					KEY_Z = (Keys)int.Parse(reader.ReadLine());
					KEY_X = (Keys)int.Parse(reader.ReadLine());
				}
				catch (Exception ex)
				{
					Debug.WriteLine("ERROR: キー設定を読み込めませんでした err: " + ex.Message);
				}
				finally
				{
					reader.Close();
				}
				return;
			}
			KEY_UP = Keys.Up;
			KEY_DN =Keys.Down;
			KEY_R = Keys.Right;
			KEY_L =Keys.Left;
			KEY_Z =Keys.Z;
			KEY_X = Keys.X;
		}

		private int keyStatus = 0;
		private int keyStatusBack = 0;
		private bool keyFrameSent = false;
		private void MainForm_KeyDown(object sender, KeyEventArgs e)
		{
			if(e.KeyCode == KEY_UP)keyStatusBack |= (int) KEYBOARD.Up;
			else if(e.KeyCode == KEY_DN)keyStatusBack |= (int) KEYBOARD.Down;
			else if(e.KeyCode == KEY_R)keyStatusBack |= (int) KEYBOARD.Right;
			else if(e.KeyCode == KEY_L)keyStatusBack |= (int) KEYBOARD.Left;
			else if(e.KeyCode == KEY_Z)keyStatusBack |= (int)KEYBOARD.Z;
			else if(e.KeyCode == KEY_X)keyStatusBack |= (int) KEYBOARD.X;

			keyStatus = keyStatusBack;	
		}

		private void MainForm_KeyUp(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == KEY_UP) keyStatusBack &= (~(int)KEYBOARD.Up);
			else if (e.KeyCode == KEY_DN) keyStatusBack &= (~(int)KEYBOARD.Down);
			else if (e.KeyCode == KEY_R) keyStatusBack &= (~(int)KEYBOARD.Right);
			else if (e.KeyCode == KEY_L) keyStatusBack &= (~(int)KEYBOARD.Left);
			else if (e.KeyCode == KEY_Z) keyStatusBack &= (~(int)KEYBOARD.Z);
			else if (e.KeyCode == KEY_X) keyStatusBack &= (~(int)KEYBOARD.X);
			else if (e.KeyCode == Keys.Escape)
			{
				Kill();
			}
			else if (e.KeyCode == Keys.F11)
			{
				FullScreen = !FullScreen;
            }
            else if (e.KeyCode == Keys.F12)
            {
#if DEBUG
                var dlg = new EditFlag();
                dlg.ShowDialog();
#endif
            }
            else if (e.KeyCode == Keys.F1)
            {
                StageManager.CurrentDataSet.Debug();
            }
			keyFrameSent = false;
		}

		public void ResetKey()
		{
			keyStatus = keyStatusBack = 0;
		}

		private bool FullScreen
		{
			get
			{
				return this.FormBorderStyle == System.Windows.Forms.FormBorderStyle.None;
			}
			set
			{
				if (value)
				{
					if (this.WindowState == FormWindowState.Maximized)
						this.WindowState = FormWindowState.Normal;
					this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
					this.WindowState = FormWindowState.Maximized;
					Cursor.Position = new Point(this.Width, this.Height);
					
					this.Activate();
				}
				else
				{
					this.WindowState = FormWindowState.Normal;
					this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
					this.Cursor = Cursors.Default;
				}
			}
		}

		Graphics gw, gc;
		Bitmap canvas;
		public void init()
		{
			LoadKey();
			resetWindowSize();
			canvas = new Bitmap(SCREEN_WIDTH, SCREEN_HEIGHT);
			ImageManager.Init();
			gw = this.pictureBox1.CreateGraphics();
			gc = Graphics.FromImage(canvas);
			Widghets = new WidghetsManager();
			Effects = new EffectsManager();
			StageManager.Init();
#if DEBUG
            Debug.WriteLine("#### DEBUG KEY INFO####");
            Debug.WriteLine("F1: SHOW_FLAGS");
            Debug.WriteLine("F12: EDIT FLAG");
#endif
		}

		private void resetWindowSize()
		{
			this.Size = new Size(
				this.Width + SCREEN_WIDTH - this.pictureBox1.Width,
				this.Height + SCREEN_HEIGHT - this.pictureBox1.Height);
		}

		public void start()
		{
			init();
		}

		private object lockedObject = null;
		public void Lock(object obj)
		{
			if(obj != null)
			{
				lockedObject = obj;
			}
		}

		public void UnLock(object obj)
		{
			if (lockedObject == obj)
			{
				lockedObject = null;
			}
		}

		public WidghetsManager Widghets { get; private set; }

		public EffectsManager Effects { get; private set; }

		public void Tick(bool isDelay)
		{
			if (StageManager.AvailableStage == null) return;
			if (lockedObject != null) return;
			bool onlyModal = Widghets.HasModal || Effects.HasModal;
			if(!onlyModal) StageManager.AvailableStage.Update(onlyModal ? 0 : keyStatus);
			Widghets.Update(keyStatus, onlyModal);
			Effects.Update();
			if (!keyFrameSent)
			{
				keyStatus = keyStatusBack;
				keyFrameSent = true;
			}
			
			if (!isDelay)
			{
				gc.ResetTransform();
				gc.Clear(this.pictureBox1.BackColor);
				StageManager.AvailableStage.Draw(gc, canvas.Width, canvas.Height);
				Widghets.Draw(gc);
				gc.ResetTransform();
				Effects.Draw(canvas, gc, gw, SCREEN_WIDTH, SCREEN_HEIGHT, this.pictureBox1.Width, this.pictureBox1.Height);
			}

			if (effectSoundBuf.Count > 0)
			{
				if (effectSoundWorker == null)
				{
					effectSoundWorker = new BackgroundWorker();
					effectSoundWorker.DoWork += backgroundWorker_DoWork;
				}
				if(!effectSoundWorker.IsBusy) effectSoundWorker.RunWorkerAsync();
			}
			if (killed) this.Close();
		}

		private bool killed = false;
		public static void Kill()
		{
			form.killed = true;
		}

		public static void PlaySound(string name)
		{
			if (name == "")
			{
				form.musicPlayer1.Stop();
			}
			else
			{
				string fname = System.Windows.Forms.Application.StartupPath + @"\musics\" + name;
				if (!System.IO.File.Exists(fname))
				{
					if (System.IO.File.Exists(fname + ".mid")) fname += ".mid";
					else if (System.IO.File.Exists(fname + ".mp3")) fname += ".mp3";
					else if (System.IO.File.Exists(fname + ".wav")) fname += ".wav";
					else return;
				}
				form.musicPlayer1.Repeat = true;
				form.musicPlayer1.Source = new Uri(fname);
				form.musicPlayer1.Play();
			}
		}

		static BackgroundWorker effectSoundWorker = null;
		static List<string> effectSoundBuf = new List<string>();
		static SoundPlayer player = null;
		public static void PlayEffectSound(string name, bool possible=false)
		{
			string fname = System.Windows.Forms.Application.StartupPath + @"\sounds\" + name;
			//if (!System.IO.File.Exists(fname))
			//{
			//    if (System.IO.File.Exists(fname + ".wav")) fname += ".wav";
			//    else return;
			//}
			if (!effectSoundPlayerList.ContainsKey(fname))
			{
				if (effectSoundPlayerList.ContainsKey(fname + ".wav")) fname += ".wav";
				else if (System.IO.File.Exists(fname + ".wav")) fname += ".wav";
				else return;
			}
			if (possible)
			{
				effectSoundBuf.Insert(0, fname);
			}
			else
			{
				effectSoundBuf.Add(fname);
			}
		}

		private void MainForm_SizeChanged(object sender, EventArgs e)
		{
			gw = this.pictureBox1.CreateGraphics();
		}

		private void pictureBox1_DoubleClick(object sender, EventArgs e)
		{
			this.WindowState = FormWindowState.Normal;
			FullScreen = false;
			resetWindowSize();
		}

		private void MainForm_Deactivate(object sender, EventArgs e)
		{
			Lock(this);
		}

		private void MainForm_Activated(object sender, EventArgs e)
		{
			UnLock(this);
		}

		static Dictionary<string, System.Media.SoundPlayer> effectSoundPlayerList = new Dictionary<string, SoundPlayer>();
		private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
		{
			while(effectSoundBuf.Count>0)
			{
				string m = effectSoundBuf[0];
				if (effectSoundPlayerList.ContainsKey(m))
				{
					effectSoundPlayerList[m].Stop();
					effectSoundPlayerList[m].PlaySync();
				}
				else
				{
					effectSoundPlayerList.Add(m, player = new System.Media.SoundPlayer(effectSoundBuf[0]));
					player.PlaySync();
				}
				//effectSoundBuf.RemoveAt(0);
				effectSoundBuf.Clear();
			}
		}

	}
}
