using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using Nlgp1.StageEditor.Notifies;

namespace Nlgp1.StageEditor.Controls {
	public partial class LayerChipsetControl : UserControl {
		private int chipSize = 1;
		private ChipsetImage chipsetImage = ChipsetImage.None;
		private SortedDictionary< int , LayerChipNotify > chipTable = new SortedDictionary< int , LayerChipNotify >();
		private LayerNotify currentLayer = LayerNotify.None;
		private LayerChipNotify currentChip = LayerChipNotify.None;

		private int  scrollThick = 17;
		private int ThumbnailClientWidth {
			get {
				return ChipThumbnailBase.Width - scrollThick;
			}
		}

		public LayerChipsetControl()
			: base() {
			InitializeComponent();

			this.Load += UpdateSize;
			this.Resize += UpdateSize;
			this.ChipThumbnail.MouseClick += ChipThumbnail_MouseClick;
			this.ChipThumbnail.Paint += ChipThumbnail_Paint;

			this.AddButton.Click += ( sender , e ) => OnChipCommand( "Add" );
			this.DeleteButton.Click += ( sender , e ) => OnChipCommand( "Delete" );
		}

		#region PropertyChanged
		public void MapData_PropertyChanged( object sender , PropertyChangedEventArgs e ) {
			var stage = (StageNotify)sender;
			if( e.PropertyName == "Create" )
				UpdateStageProperty( stage );
		}

		public void ChipGridData_PropertyChanged( object sender , PropertyChangedEventArgs e ) {
			if( e.PropertyName == "LoadLayerImage" )
				Refresh();
			if( e.PropertyName == "AddChipData" )
				UpdateSize( this , null );
			if( e.PropertyName == "RemoveChipData" )
				UpdateSize( this , null );
		}

		public void ChipData_PropertyChanged( object sender , PropertyChangedEventArgs e ) {
			if( e.PropertyName == "SetProperty" )
				Refresh();
		}

		public void EditorData_PropertyChanged( object sender , PropertyChangedEventArgs e ) {
			var editor = (EditorNotify)sender;
			if( e.PropertyName == "CurrentLayer" )
				UpdateEditorProperty( editor );
			if( e.PropertyName == "CurrentChip" )
				UpdateEditorProperty( editor );
		}

		private void UpdateStageProperty( StageNotify stage ) {
			this.chipSize = stage.ChipSize;
			UpdateSize( this , null );
			Refresh();
		}

		private void UpdateEditorProperty( EditorNotify editor ) {
			this.currentLayer = editor.CurrentLayer;
			this.currentChip = editor.CurrentChip;
			this.chipsetImage = currentLayer.ChipsetImage;
			this.chipTable = currentLayer.ChipTable;

			this.CommandPanel.Visible = ( currentLayer != LayerNotify.None );

			UpdateSize( this , null );
			Refresh();
		}
		#endregion

		private void UpdateSize( object sender , EventArgs e ) {
			if( chipTable.Count == 0 )
				return;

			var clientWidth = ThumbnailClientWidth;
			var clientHeight = ChipThumbnailBase.Height;

			var chipNum = chipTable.Count;

			var width = ( clientWidth / chipSize ) * chipSize;
			var column = width / chipSize;

			var newColumn = Math.Max( column , 1 );
			var newRow = (int)Math.Ceiling( (float)chipNum / newColumn );
			newRow = Math.Max( newRow , 1 );

			var newWidth = newColumn * chipSize + 1;
			var newHeight = newRow * chipSize + 1;

			this.ChipThumbnail.Size = new Size( newWidth , newHeight );
		}

		public void ChipThumbnail_MouseClick( object sender , MouseEventArgs e ) {
			if( e.Button != MouseButtons.Left )
				return;

			var clientWidth = ThumbnailClientWidth;

			var width = ( clientWidth / chipSize ) * chipSize;
			var height = ( ChipThumbnail.Height / chipSize ) * chipSize;
			var isRangeOver = ( e.X > width || e.Y > height );
			if( isRangeOver )
				return;

			var row = height / chipSize;
			var column = width / chipSize;
			var x = e.X / chipSize;
			var y = e.Y / chipSize;
			var gridNumber = x + y * column;

			if( gridNumber >= chipTable.Count )
				return;

			var chip = chipTable[gridNumber];

			OnChipClicked( chip );
		}

		public void ChipThumbnail_Paint( object sender , PaintEventArgs e ) {
			var clientWidth = ThumbnailClientWidth;
			var column = clientWidth / chipSize;
			column = Math.Max( column , 1 );

			var gridPen = Pens.Black;
			var i = 0;
			foreach( var chip in chipTable.Values ) {
				var x = ( i % column ) * chipSize;
				var y = ( i / column ) * chipSize;
				var imageNumber = chip.Index;
				var image = chipsetImage[imageNumber];
				if( image != null ) {
					e.Graphics.DrawImage( image , x , y );
				}

				var rect = new Rectangle( x , y , chipSize , chipSize );
				e.Graphics.DrawRectangle( gridPen , rect );
				i++;
			}

			var currentPen = Pens.Yellow;
			var number = currentChip.Index;
			var currentX = ( number % column ) * chipSize;
			var currentY = ( number / column ) * chipSize;
			var currentRect = new Rectangle( currentX , currentY , chipSize , chipSize );
			e.Graphics.DrawRectangle( currentPen , currentRect );
		}


		private void ImageLoadButton_Click( object sender , EventArgs e ) {
			var reuslt = LoadImageDialog.ShowDialog();
			if( reuslt != DialogResult.OK )
				return;

			OnImageLoad( LoadImageDialog.FileName );
		}

		private void ImageAddButton_Click( object sender , EventArgs e ) {
			MessageBox.Show( "未実装です\nどなたか実装してくれるとうれしいかも" );
		}

		#region ChipClickedEvent
		public event ChipClickedEventHandler ChipClicked;
		private void OnChipClicked( LayerChipNotify chip ) {
			if( ChipClicked == null )
				return;

			var e = new ChipClickedEventArg( chip );
			ChipClicked( this , e );
		}

		public delegate void ChipClickedEventHandler( object sender , ChipClickedEventArg e );
		public class ChipClickedEventArg : EventArgs {
			public LayerChipNotify ChipData {
				get;
				set;
			}
			public ChipClickedEventArg( LayerChipNotify chip ) {
				this.ChipData = chip;
			}
		}
		#endregion

		#region ChipCommand

		public event ChipCommandEventHandler ChipCommand;
		private void OnChipCommand( string commnad ) {
			if( ChipCommand == null )
				return;

			var e = new ChipCommandEventArgs( commnad );
			ChipCommand( this , e );
		}

		public delegate void ChipCommandEventHandler( object sender , ChipCommandEventArgs e );
		public class ChipCommandEventArgs : EventArgs {
			public string Commnad {
				get;
				private set;
			}
			public ChipCommandEventArgs( string command ) {
				this.Commnad = command;
			}
		}
		#endregion

		#region ImageLoad
		public event FileOpenEventHander ImageLoad;
		public void OnImageLoad( string path ) {
			if( ImageLoad == null )
				return;

			var e = new FileOpenEventArgs( path );
			ImageLoad( this , e );
		}

		public delegate void FileOpenEventHander( object sender , FileOpenEventArgs e );
		public class FileOpenEventArgs : EventArgs {
			public string Path {
				get;
				private set;
			}
			public FileOpenEventArgs( string path ) {
				this.Path = path;
			}
		}
		#endregion

		private void AddButton_Click( object sender , EventArgs e ) {

		}


	}
}