///////////////////////////////
// Boids.cs
// Copyright (c) 2026 by ysama
///////////////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;				//Assembly使用の為
using System.Resources;					//リソース使用の為
using Boids_for_CS;						//Boids_for_CS.dll使用の為

namespace Boids_EXE
{
	//名前空間共用静的クラス
	static class Title
	{
		public const string Ver = "Boids for C# Ver 2.1";
	}

	//Boids_Csクラス（ウィンドウプログラム本体）
	public class Boids_Cs : Form
	{
		//クラスメンバーフィールド
		Assembly myOwn = Assembly.GetEntryAssembly();
		int NoOfBoids = 0;
		bool Introvert = false;
		bool Sociopath = false;
		//クラスメンバーコントロール
		MenuStrip menuStrip;						//メニュー
		ToolStrip toolStrip;						//ツールバー
		ToolStripButton[] tsButton;					//ツールバーボタン
		StatusStrip statusStrip;					//ステータスバー
		ToolStripStatusLabel[] tssl;				//ステータスバーラベル
		Boids boids;								//Boidsクラスインスタンス
		bool drawFlag = false;						//飛行跡フラグ
		//クラス内で参照されるメニューアイテム
		ToolStripMenuItem miStart;
		ToolStripMenuItem miStop;

		[STAThread]
		public static void Main()					//エントリーポイント
		{
			Application.Run(new Boids_Cs());
		}

		public Boids_Cs()							//コンストラクター
		{
			this.Icon = Icon.ExtractAssociatedIcon(myOwn.Location);	//プログラムアイコン
			this.StartPosition = FormStartPosition.CenterScreen;	//画面中央表示
			//メニューバー、ツールバー、ステータスバーの高さ（71）を追加してサイズを設定
			this.ClientSize = new Size(1280, 711);
			this.Text = "Boids for C#";
			//起動時処理
			this.Load += Boids_Load;
		}

		private void Boids_Load(object sender, EventArgs e)
		{
			//フォームのレイアウトを一時停止
			this.SuspendLayout();
			//ツールバーとステータスバーの設定
			MakeBars();
			//メニューの作成（MenuStripはコントロールであり、上からの並びはDock投入のFILO順となる）
			MakeMenu();
			//メニュー・ツールバーボタンの状態設定
			SetStatus(false);
			//Boidsクラスインスタンスの作成
			boids = new Boids();
			boids.Dock = DockStyle.Fill;
			this.Controls.Add(boids);
			//フォームのレイアウトを再開
			this.ResumeLayout(false);
			this.PerformLayout();
		}

		//メニューの作成
		private void MakeMenu()
		{
			//メインメニュー作成
			menuStrip = new MenuStrip();
			menuStrip.Dock = DockStyle.Top;
			menuStrip.SuspendLayout();
			//メインメニューアイテム付加
			ToolStripMenuItem miFile = new ToolStripMenuItem();		//「ファイル」メニュー
			miFile.Text = "ファイル(&F)";
			menuStrip.Items.Add(miFile);
			ToolStripMenuItem miGame = new ToolStripMenuItem();		//「ゲーム」メニュー
			miGame.Text = "ゲーム(&G)";
			menuStrip.Items.Add(miGame);
			ToolStripMenuItem miHelp = new ToolStripMenuItem();		//「ヘルプ」メニュー
			miHelp.Text = "ヘルプ(&H)";
			menuStrip.Items.Add(miHelp);
			//「ファイル」メニューアイテム付加
			ToolStripMenuItem miSetUp = new ToolStripMenuItem();	//「設定」メニューアイテム
			miSetUp.Text = "Boidsの設定(&U)";
			miSetUp.Click += OnSetUp_Click;
			miSetUp.ShortcutKeys = Keys.Control | Keys.U;
			miFile.DropDownItems.Add(miSetUp);
			ToolStripMenuItem miExit = new ToolStripMenuItem();		//「終了」メニューアイテム
			miExit.Text = "終了(&X)";
			miExit.Click += OnExit_Click;
			miExit.ShortcutKeys = Keys.Control | Keys.X;
			miFile.DropDownItems.Add(miExit);
			//「ゲーム」メニューアイテム付加
			miStart = new ToolStripMenuItem();						//「ゲーム開始」メニューアイテム
			miStart.Text = "ゲーム開始(&S)";
			miStart.Click += OnStart_Click;
			miStart.ShortcutKeys = Keys.Control | Keys.S;
			miGame.DropDownItems.Add(miStart);
			miStop = new ToolStripMenuItem();						//「ゲーム中止」メニューアイテム
			miStop.Text = "ゲーム中止(&A)";
			miStop.Click += OnStop_Click;
			miStop.ShortcutKeys = Keys.Control | Keys.A;
			miGame.DropDownItems.Add(miStop);
			miGame.DropDownItems.Add(new ToolStripSeparator());		//セパレーター
			ToolStripMenuItem miTrail = new ToolStripMenuItem();	//「飛行跡」メニューアイテム
			miTrail.Text = "飛行跡(&T)";
			miTrail.Click += OnTrail_Click;
			miTrail.ShortcutKeys = Keys.Control | Keys.T;
			miGame.DropDownItems.Add(miTrail);
			//「ヘルプ」メニューアイテム付加
			ToolStripMenuItem miHowtoPlay = new ToolStripMenuItem();//「Boidsについて」メニューアイテム
			miHowtoPlay.Text = "Boidsについて(&B)";
			miHowtoPlay.Click += OnAboutBoids_Click;
			miHowtoPlay.ShortcutKeys = Keys.Control | Keys.B;
			miHelp.DropDownItems.Add(miHowtoPlay);
			miGame.DropDownItems.Add(new ToolStripSeparator());		//セパレーター
			ToolStripMenuItem miVer = new ToolStripMenuItem();		//「バージョン」メニューアイテム
			miVer.Text = "バージョン(&V)";
			miVer.Click += OnVersion_Click;
			miVer.ShortcutKeys = Keys.F2;
			miHelp.DropDownItems.Add(miVer);
			//メインメニューに設定して表示
			this.MainMenuStrip = menuStrip;
			this.Controls.Add(menuStrip);
			menuStrip.ResumeLayout(false);
			menuStrip.PerformLayout();
		}

		//ツールバーとステータスバーの作成
		private void MakeBars()
		{
			//ToolStripクラスインスタンスの生成
			this.toolStrip = new ToolStrip();
			this.toolStrip.Dock = DockStyle.Top;
			//ツールバーのレイアウトを一時停止
			this.toolStrip.SuspendLayout();
			//ToolStripButton配列を作成
			this.tsButton = new ToolStripButton[6];
			//本プログラムの埋め込みリソースのリソースマネージャーを作成
			ResourceManager rm = new ResourceManager("Boids", myOwn);
			//ツールバービットマップの読み込み
			ImageList imgList = new ImageList();
			imgList.ImageSize = new Size(16, 15);
			imgList.Images.AddStrip((Bitmap)rm.GetObject("ToolBar"));
			imgList.TransparentColor = Color.FromArgb(0xFF, 0xFF, 0xFF);	//ToolBar.bmpの背景色

			//ToolStripButton[0]を作成
			this.tsButton[0] = new ToolStripButton();
			this.tsButton[0].Text = "Boidsの設定";							//テキスト設定
			this.tsButton[0].Image = (Bitmap)imgList.Images[0];				//画像設定
			this.tsButton[0].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
			this.tsButton[0].Click += OnSetUp_Click;						//Clickイベントハンドラ追加
			this.toolStrip.Items.Add(this.tsButton[0]);						//ボタンを追加
			//ToolStripButton[1]を作成
			this.tsButton[1] = new ToolStripButton();
			this.tsButton[1].Text = "Boidsの終了";							//テキスト設定
			this.tsButton[1].Image = (Bitmap)imgList.Images[1];				//画像設定
			this.tsButton[1].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
			this.tsButton[1].Click += OnExit_Click;							//Clickイベントハンドラ追加
			this.toolStrip.Items.Add(this.tsButton[1]);						//ボタンを追加
			//セパレーターを挿入
			this.toolStrip.Items.Add(new ToolStripSeparator());
			//ToolStripButton[2]を作成
			this.tsButton[2] = new ToolStripButton();
			this.tsButton[2].Text = "ゲーム開始";							//テキスト設定
			this.tsButton[2].Image = (Bitmap)imgList.Images[2];				//画像設定
			this.tsButton[2].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
			this.tsButton[2].Click += OnStart_Click;							//Clickイベントハンドラ追加
			this.toolStrip.Items.Add(this.tsButton[2]);						//ボタンを追加
			//ToolStripButton[3]を作成
			this.tsButton[3] = new ToolStripButton();
			this.tsButton[3].Text = "ゲーム中止";							//テキスト設定
			this.tsButton[3].Image = (Bitmap)imgList.Images[3];				//画像設定
			this.tsButton[3].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
			this.tsButton[3].Click += OnStop_Click;							//Clickイベントハンドラ追加
			this.toolStrip.Items.Add(this.tsButton[3]);						//ボタンを追加
			//セパレーターを挿入
			this.toolStrip.Items.Add(new ToolStripSeparator());
			//ToolStripButton[4]を作成
			this.tsButton[4] = new ToolStripButton();
			this.tsButton[4].Text = "飛行跡";								//テキスト設定
			this.tsButton[4].Image = (Bitmap)imgList.Images[4];				//画像設定
			this.tsButton[4].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
			this.tsButton[4].Click += OnTrail_Click;					//Clickイベントハンドラ追加
			this.toolStrip.Items.Add(this.tsButton[4]);						//ボタンを追加
			//ToolStripButton[5]を作成
			this.tsButton[5] = new ToolStripButton();
			this.tsButton[5].Text = "バージョン";							//テキスト設定
			this.tsButton[5].Image = (Bitmap)imgList.Images[5];				//画像設定
			this.tsButton[5].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
			this.tsButton[5].Click += OnVersion_Click;						//Clickイベントハンドラ追加
			this.toolStrip.Items.Add(this.tsButton[5]);						//ボタンを追加
			//ツールバーの設定
			this.Controls.Add(this.toolStrip);
			//ツールバーのレイアウトを再開
			this.toolStrip.ResumeLayout(false);
			this.toolStrip.PerformLayout();

			//StatusStripクラスインスタンスの生成
			this.statusStrip = new StatusStrip();
			this.statusStrip.Dock = DockStyle.Bottom;
			//ステータスバーにパネルとテキストを追加
			tssl = new ToolStripStatusLabel[2];
			tssl[0] = new ToolStripStatusLabel();
			tssl[0].BorderSides = ToolStripStatusLabelBorderSides.All;
			tssl[0].BorderStyle = Border3DStyle.SunkenInner;
			tssl[0].BackColor = SystemColors.Control;
			tssl[0].TextAlign = ContentAlignment.MiddleLeft;
			tssl[0].Text = Title.Ver;
			tssl[0].AutoSize = true;
			tssl[1] = new ToolStripStatusLabel();
			tssl[1].BorderSides = ToolStripStatusLabelBorderSides.All;
			tssl[1].BorderStyle = Border3DStyle.SunkenInner;
			tssl[1].BackColor = SystemColors.Control;
			tssl[1].TextAlign = ContentAlignment.MiddleLeft;
			tssl[1].Text = "（Boidsの情報）";
			tssl[1].ToolTipText = tssl[1].Text;								//ToolTip設定
			tssl[1].Spring = true;
			statusStrip.Items.AddRange(tssl);
			statusStrip.ShowItemToolTips = true;							//ToolTip表示
			this.Controls.Add(this.statusStrip);							//StatusStrip(ステータスバー)を追加
		}

		//終了処理
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			base.OnFormClosing(e);
			DialogResult dr = MessageBox.Show("終了しますか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
			if(dr == DialogResult.No)
			{
				e.Cancel = true;
			}
		}

		//「設定」処理
		private void OnSetUp_Click(object sender, EventArgs e)
		{
			SetUpDlg suDlg = new SetUpDlg();
			suDlg.ShowDialog(this);
			NoOfBoids = suDlg.NoOfBoids;
			Introvert = suDlg.Introvert;
			Sociopath = suDlg.Sociopath;
			boids.SetBackGround(suDlg.Background);
			suDlg.Dispose();
		}

		//「終了」処理
		private void OnExit_Click(object sender, EventArgs e)
		{
			Close();	//修了確認はOnClosingメソッドで行う
		}

		//「ゲーム開始」処理
		private void OnStart_Click(object sender, EventArgs e)
		{
			if(NoOfBoids == 0)
			{
				MessageBox.Show("開始前に「ファイル」メニューまたはツールバーボタンの「Boidsの設定」を行ってください", "確認", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}
			else
			{
				DialogResult res = MessageBox.Show("新しいゲームですか（はい）、中断したゲームの再開ですか（いいえ）？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
				if(res == DialogResult.Yes)
				{
					//擬鳥の生成
					tssl[1].Text = boids.CreateBoids(NoOfBoids, Introvert, Sociopath);
					tssl[1].ToolTipText = tssl[1].Text;			//ToolTip設定
				}
			}
			//Boids開始
			boids.Start();
			//メニュー・ツールバーボタンの状態設定
			SetStatus(true);
		}

		//「ゲーム中止」処理
		private void OnStop_Click(object sender, EventArgs e)
		{
			boids.Stop();
			//メニュー・ツールバーボタンの状態設定
			SetStatus(false);
			//Boidsの結果表示
			boids.Result();
		}

		//「飛行跡」処理
		private void OnTrail_Click(object sender, EventArgs e)
		{
			drawFlag = !drawFlag;
			tsButton[4].Checked = drawFlag;
			boids.DrawTrail(drawFlag);
		}

		//「Boidsについて」処理
		private void OnAboutBoids_Click(object sender, EventArgs e)
		{
			string data = String.Empty;				//"AboutBoids.txt"ファイル入力
			try
			{
				using(System.IO.StreamReader file = new System.IO.StreamReader("AboutBoids.txt", System.Text.Encoding.UTF8))	//入力UTF-8
				{
					data = file.ReadToEnd();		//ファイルを読む
					file.Close();					//ファイルを閉じる
				}
			}
			catch(System.IO.FileNotFoundException ex)
			{
				string errMessage = "「Boidsについて」のファイル（\"AboutBoids.txt\"）を表示できません。" + Environment.NewLine + ex.Message;
				MessageBox.Show(errMessage, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			txtDlg txtdlg = new txtDlg(Icon, data);
			txtdlg.ShowDialog(this);
			txtdlg.Dispose();
		}

		//「バージョン」処理
		private void OnVersion_Click(object sender, EventArgs e)
		{
			VersionDlg verDlg = new VersionDlg(this.Icon);	//Versionダイアログ表示
			verDlg.ShowDialog(this);
			verDlg.Dispose();
		}

		//メニュー・ボタンの状態を設定する
		private void SetStatus(bool game = false)
		{
			miStart.Enabled = !game;		//「ゲーム開始」メニューアイテム
			miStop.Enabled = game;			//「ゲーム中止」メニューアイテム
			tsButton[2].Enabled = !game;	//「ゲーム開始」ボタン
			tsButton[3].Enabled = game;		//「ゲーム中止」ボタン
		}
	}

	//////////////////////
	//Boids設定ダイアログ
	//////////////////////
	class SetUpDlg : Form
	{
		//ダイアログのフィールド
		public int NoOfBoids;
		public bool Introvert;
		public bool Sociopath;
		public bool Background;
		//ダイアログのコントロール
		Button BtnOK;
		ComboBox DDList;		//DropDownStyleプロパティをDropDownList
		CheckBox IvCheck;		//Introvert付加指定
		CheckBox SpCheck;		//Sociopath付加指定
		CheckBox BkCheck;		//背景付加指定

		public SetUpDlg()
		{
			//ダイアログの属性設定
			this.Text = "Boidsの環境設定";
			this.ClientSize = new Size(140, 170);
			this.ControlBox = false;		//システムボタン無効
			this.ShowInTaskbar = false;		//タスクバー上非表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;		// 境界のスタイル
			this.StartPosition = FormStartPosition.CenterParent;	//親ダイアログ中央に配置
			this.Load += Form_Load;
		}

		//OnLoad処理
		private void Form_Load(object sender, EventArgs e)
		{
			//コントロールの属性設定
			BtnOK = new Button();
			BtnOK.Location = new Point((ClientSize.Width - BtnOK.Width) / 2, ClientSize.Height - BtnOK.Height - 10);
			BtnOK.Text = "決定";
			BtnOK.AutoSize = true;
			BtnOK.Click += new EventHandler(OnOK_Click);
			this.Controls.Add(BtnOK);

			DDList = new ComboBox();
			DDList.DropDownStyle = ComboBoxStyle.DropDownList;
			DDList.Location = new Point((ClientSize.Width - DDList.Width) / 2, 10);
			DDList.MaxDropDownItems = 8;
			for(int i = 0; i < DDList.MaxDropDownItems; i++)
			{
				string item = (i * 40 + 60).ToString() + " boids";
				DDList.Items.Add(item);
			}
			DDList.SelectedIndex = 1;
			this.Controls.Add(DDList);

			IvCheck = new CheckBox();
			IvCheck.TextAlign = ContentAlignment.MiddleLeft;
			IvCheck.Location = new Point((ClientSize.Width - IvCheck.Width) / 2, 40);
			IvCheck.Size = new Size(160, 24);
			IvCheck.Text = "Introvertを付加";
			this.Controls.Add(IvCheck);

			SpCheck = new CheckBox();
			SpCheck.TextAlign = ContentAlignment.MiddleLeft;
			SpCheck.Location = new Point((ClientSize.Width - SpCheck.Width) / 2, 70);
			SpCheck.Size = new Size(160, 24);
			SpCheck.Text = "Sociopathを付加";
			this.Controls.Add(SpCheck);

			BkCheck = new CheckBox();
			BkCheck.TextAlign = ContentAlignment.MiddleLeft;
			BkCheck.Location = new Point((ClientSize.Width - BkCheck.Width) / 2, 100);
			BkCheck.Size = new Size(160, 24);
			BkCheck.Text = "背景を付加";
			this.Controls.Add(BkCheck);
		}

		//OKボタン処理
		protected void OnOK_Click(object sender, EventArgs e)
		{
			if(DDList.SelectedIndex == -1)
				MessageBox.Show("コンボボックスが選択されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			else
			{
				NoOfBoids = DDList.SelectedIndex * 40 + 60;
				Introvert = IvCheck.Checked;
				Sociopath = SpCheck.Checked;
				Background = BkCheck.Checked;
				Close();
			}
		}
	}

	/////////////////////////
	//テキスト表示ダイアログ
	/////////////////////////
	public class txtDlg : Form
	{
		//クラスフィールド
		string txtData;
		//クラスコントロール
		TextBox txtBox;
		Button extBtn;

		public txtDlg(Icon ico, string data = "", string title = "Boidsについて")
		{
			txtData = data;
			this.Icon = ico;
			this.Size = new Size(800, 500);
			this.MinimumSize = new Size(640, 480);
			this.Text = title;
			this.StartPosition = FormStartPosition.CenterParent;	//親ダイアログ中央に配置
			this.Load += txtDlg_Load;
		}

		protected override void OnResize(EventArgs e)
		{
			//OnResize既定処理
			base.OnResize(e);
			//txtBoxコントロールを中央に配置
			if(txtBox != null)	//ダイアログ作成時はnullでエラーとなる為
				txtBox.Left = (ClientSize.Width - txtBox.Width) / 2;
		}

		private void txtDlg_Load(object sender, EventArgs e)
		{
			//Exitボタン
			extBtn = new Button();
			extBtn.Location = new Point((ClientSize.Width - extBtn.Width) / 2, ClientSize.Height - extBtn.Height - 10);
			extBtn.Text = "終了";
			extBtn.Anchor = AnchorStyles.Bottom;
			extBtn.Click += extBtn_Click;
			this.Controls.Add(extBtn);

			//テキストボックス
			txtBox = new TextBox();
			txtBox.Width = ClientSize.Width - 20;
			txtBox.Height = ClientSize.Height - extBtn.Height - 30;
			txtBox.Location = new Point(10, 10);
			txtBox.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
			txtBox.BackColor = Control.DefaultBackColor;
			txtBox.Multiline = true;
			txtBox.ScrollBars = ScrollBars.Both;
			txtBox.WordWrap  = false;
			//テキストデータ
			txtBox.Text = txtData;
			//FormにTextBoxを追加
			this.Controls.Add(txtBox);
		}

		private void extBtn_Click(object sender, EventArgs e)
		{
			//終了する
			Close();
		}
	}

	/////////////////////
	//Version ダイアログ
	/////////////////////
	class VersionDlg : Form
	{
		public VersionDlg(Icon ico)
		{
			//ダイアログの属性設定
			this.Text = "バーション情報";
			this.ClientSize = new Size(320, 100);
			this.MaximizeBox = false;		// 最大化ボタン
			this.MinimizeBox = false;		// 最小化ボタン
			this.ShowInTaskbar = false;		//タスクバー上表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;		// 境界のスタイル
			this.StartPosition = FormStartPosition.CenterParent;	// 親フォームの中央に配置
			//コントロールの属性設定
			Button btnOK = new Button();
			btnOK.Size = new Size(40, 28);
			btnOK.Location = new Point(ClientSize.Width - btnOK.Width - 10, (ClientSize.Height - btnOK.Height) / 2);
			btnOK.Text = "OK";
			btnOK.Click += new EventHandler(OnOK_Click);
			Label imglabel = new Label();
			imglabel.Size = new Size(40, 40);
			imglabel.Location = new Point(10, (ClientSize.Height - imglabel.Height) / 2);
			imglabel.BorderStyle = BorderStyle.Fixed3D;
			imglabel.Image = ico.ToBitmap();						//親のシステムアイコン
			Label label = new Label();
			label.Size = new Size(ClientSize.Width - imglabel.Width - btnOK.Width - 40, ClientSize.Height- 20);
			label.Location = new Point(imglabel.Width + 20, (ClientSize.Height - label.Height) / 2);
			label.BorderStyle = BorderStyle.Fixed3D;
			label.Text = Title.Ver + "\r\nCopyright (c) 2026 by Ysama\r\n(written in Microsoft C#)";
			label.TextAlign = ContentAlignment.MiddleCenter;
			label.Font = new Font("Times New Roman", 10, FontStyle.Bold);
			this.Controls.Add(btnOK);
			this.Controls.Add(imglabel);
			this.Controls.Add(label);
		}

		private void OnOK_Click(object sender, EventArgs e)
		{
			Close();
		}
	}
}
