#if MEMMONITOR
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace TIASshot {

    /// <summary>
    /// メモリ観測ウィンドウ（MEMMONITOR 限定）。
    /// TIASshot 本体プロセスのメモリ使用量をライブ折れ線グラフで表示する。
    /// 研究室デモ用：実使用時にメモリが増え続けないことを画面録画で示す。
    /// </summary>
    public partial class MemoryMonitorForm : Form {

        // ---- サンプリング記録 -------------------------------------------------
        private struct MemSample {
            public double ElapsedSec;
            public double PrivateMB;
            public double WorkingSetMB;
        }

        private readonly List<MemSample> _samples = new List<MemSample>();
        private readonly System.Windows.Forms.Timer _timer;
        private readonly Stopwatch _stopwatch = new Stopwatch();
        private bool _isRunning;

        // CSV 出力先
        private readonly string _outputDir;

        // ---- コンストラクタ ---------------------------------------------------

        public MemoryMonitorForm() {
            InitializeComponent();

            // モードラベルとウィンドウタイトルをビルド種別に応じて設定
#if LEAKY_REPRO
            lblMode.Text = "モード: リーク再現（修正前）";
            lblMode.ForeColor = System.Drawing.Color.Red;
            this.Text = "メモリ観測ウィンドウ [MEMMONITOR] — リーク再現";
#else
            lblMode.Text = "モード: 修正後";
            lblMode.ForeColor = System.Drawing.Color.Green;
            this.Text = "メモリ観測ウィンドウ [MEMMONITOR] — 修正後";
#endif

            _outputDir = Path.Combine(
                AppDomain.CurrentDomain.BaseDirectory,
                "MemMonitor_Results");
            Directory.CreateDirectory(_outputDir);

            _timer = new System.Windows.Forms.Timer();
            _timer.Interval = 500;
            _timer.Tick += Timer_Tick;

            this.FormClosing += (s, e) => {
                _timer.Stop();
            };

            // ウィンドウを開いたら自動でサンプリング開始
            this.Shown += (s, e) => StartSampling();
        }

        // ---- サンプリング制御 ------------------------------------------------

        private void StartSampling() {
            if (_isRunning) return;
            _isRunning = true;
            _stopwatch.Start();
            _timer.Start();
            btnStartStop.Text = "停止";
        }

        private void StopSampling() {
            if (!_isRunning) return;
            _isRunning = false;
            _stopwatch.Stop();
            _timer.Stop();
            btnStartStop.Text = "開始";
        }

        // ---- タイマー Tick（サンプリング本体）--------------------------------

        private void Timer_Tick(object sender, EventArgs e) {
            // Process.Refresh() で最新値を取得（GC 強制なし）
            using (var proc = Process.GetCurrentProcess()) {
                proc.Refresh();

                double elapsedSec = _stopwatch.Elapsed.TotalSeconds;
                double privateMB = proc.PrivateMemorySize64 / (1024.0 * 1024.0);
                double wsMB = proc.WorkingSet64 / (1024.0 * 1024.0);

                // 記録
                _samples.Add(new MemSample {
                    ElapsedSec = elapsedSec,
                    PrivateMB = privateMB,
                    WorkingSetMB = wsMB,
                });

                // グラフ追加
                double privateGB = privateMB / 1024.0;
                double wsGB = wsMB / 1024.0;

                chart.Series["Private"].Points.AddXY(elapsedSec, privateGB);
                chart.Series["WorkingSet"].Points.AddXY(elapsedSec, wsGB);

                // Y 軸オートスケール追従
                chart.ChartAreas["ChartArea1"].RecalculateAxesScale();

                // ラベル更新
                int n = (int)Math.Round(elapsedSec);
                lblCurrent.Text =
                    $"現在: Private {privateGB:F2} GB / WS {wsGB:F2} GB（経過 {n}s）";
            }
        }

        // ---- ボタンイベント --------------------------------------------------

        private void btnStartStop_Click(object sender, EventArgs e) {
            if (_isRunning) {
                StopSampling();
            } else {
                StartSampling();
            }
        }

        private void btnReset_Click(object sender, EventArgs e) {
            StopSampling();
            _samples.Clear();
            _stopwatch.Reset();
            chart.Series["Private"].Points.Clear();
            chart.Series["WorkingSet"].Points.Clear();
            lblCurrent.Text = "現在: --- (リセット)";
        }

        private void btnSaveCsv_Click(object sender, EventArgs e) {
            if (_samples.Count == 0) {
                MessageBox.Show("記録データがありません。", "CSV 保存",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            string path = NextCsvPath();
            var sb = new StringBuilder();
            sb.AppendLine("elapsed_sec,private_MB,ws_MB");
            foreach (var s in _samples) {
                sb.AppendLine($"{s.ElapsedSec:F3},{s.PrivateMB:F2},{s.WorkingSetMB:F2}");
            }
            File.WriteAllText(path, sb.ToString(), new UTF8Encoding(false));

            MessageBox.Show($"保存しました:\n{path}", "CSV 保存",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void btnOpenFolder_Click(object sender, EventArgs e) {
            Directory.CreateDirectory(_outputDir);
            Process.Start("explorer.exe", _outputDir);
        }

        // ---- ユーティリティ --------------------------------------------------

        private string NextCsvPath() {
            const string prefix = "mem_monitor_";
            int max = 0;
            if (Directory.Exists(_outputDir)) {
                foreach (var f in Directory.GetFiles(_outputDir, prefix + "*.csv")) {
                    string name = Path.GetFileNameWithoutExtension(f);
                    string numPart = name.Substring(prefix.Length);
                    if (int.TryParse(numPart, out int n) && n > max) max = n;
                }
            }
            return Path.Combine(_outputDir, $"{prefix}{max + 1:D4}.csv");
        }
    }
}
#endif
