using System.Collections.Generic;
using UnityEngine;

namespace ServiceSim
{
    /// <summary>
    /// ロボットの道順（v5b）。サイトが決めた曲がり角の点の並びを持つ。
    ///
    /// 2026-10-22 にエイイチと決めたこと:
    ///   Unity で道を決めるのをやめ、**道順はサイトが決めて渡す**。
    ///   サイトの試算は卓ごとの道（ふだん走らせる 1.0 m の道、届かなければ 0.8 m の道）を
    ///   もう持っているので、それを曲がり角の点の並びにして JSON に入れてある。
    ///   Unity のロボットはその点を順にたどるだけ。
    ///   人をよける・止まる・立ち往生は Unity の中で起きる（それを測るのが Unity の役目）。
    ///
    /// JSON の形（layout の routes）:
    ///   from_pass["T05"] … 受け渡し口の前 → T05 の止まる位置
    ///                      points（最初が受け渡し口の前・最後が止まる位置）/ use / width / length
    ///   between["T05|T12"] … T05 の止まる位置 → T12 の止まる位置
    ///                      逆向き（T12 → T05）は点を逆にたどる
    ///   卓 → 受け渡し口は from_pass を逆にたどる
    /// </summary>
    public class RouteBook
    {
        /// <summary>道順 1 本</summary>
        public class Route
        {
            /// <summary>曲がり角の点（XZ。y は 0）</summary>
            public readonly List<Vector3> points = new List<Vector3>();

            /// <summary>normal（1.0 m の道）/ narrow（0.8 m の道）</summary>
            public string use = "normal";

            /// <summary>その道の幅（m）</summary>
            public float width;

            /// <summary>JSON が持っている長さ（m）</summary>
            public float length;

            public bool IsNarrow { get { return use == "narrow"; } }

            /// <summary>点を結んだ長さ（m）。JSON の length と突き合わせる用</summary>
            public float PolylineLength
            {
                get
                {
                    float d = 0f;
                    for (int i = 1; i < points.Count; i++) d += Vector3.Distance(points[i - 1], points[i]);
                    return d;
                }
            }
        }

        readonly Dictionary<int, Route> _fromPass = new Dictionary<int, Route>();
        readonly Dictionary<long, Route> _between = new Dictionary<long, Route>();

        public int FromPassCount { get { return _fromPass.Count; } }
        public int BetweenCount { get { return _between.Count; } }

        static long Key(int a, int b) { return (long)a * 100000L + b; }

        public void AddFromPass(int tableId, Route r) { _fromPass[tableId] = r; }
        public void AddBetween(int a, int b, Route r) { _between[Key(a, b)] = r; }

        public Route FromPass(int tableId)
        {
            Route r;
            return _fromPass.TryGetValue(tableId, out r) ? r : null;
        }

        /// <summary>a → b の道順。逆向きしか無ければ、その点を逆にたどる</summary>
        public List<Vector3> PointsBetween(int a, int b, out Route used, out bool reversed)
        {
            reversed = false;
            if (_between.TryGetValue(Key(a, b), out used)) return new List<Vector3>(used.points);
            if (_between.TryGetValue(Key(b, a), out used))
            {
                reversed = true;
                List<Vector3> p = new List<Vector3>(used.points);
                p.Reverse();
                return p;
            }
            used = null;
            return null;
        }

        /// <summary>受け渡し口の前 → 卓</summary>
        public List<Vector3> PointsFromPass(int tableId, out Route used)
        {
            used = FromPass(tableId);
            return used != null ? new List<Vector3>(used.points) : null;
        }

        /// <summary>卓 → 受け渡し口の前（from_pass を逆にたどる）</summary>
        public List<Vector3> PointsToPass(int tableId, out Route used)
        {
            used = FromPass(tableId);
            if (used == null) return null;
            List<Vector3> p = new List<Vector3>(used.points);
            p.Reverse();
            return p;
        }

        /// <summary>その卓へ行く道が、0.8 m の道を使うか（確かめの via_narrow）</summary>
        public bool UsesNarrow(int tableId)
        {
            Route r = FromPass(tableId);
            return r != null && r.IsNarrow;
        }

        public string UseOf(int tableId)
        {
            Route r = FromPass(tableId);
            return r != null ? r.use : "";
        }

        /// <summary>報告に出す覚え書き</summary>
        public string Summary()
        {
            int narrow = 0;
            foreach (KeyValuePair<int, Route> kv in _fromPass)
                if (kv.Value.IsNarrow) narrow++;
            return "受け渡し口から " + _fromPass.Count + " 本（うち 0.8 m の道 " + narrow + " 本）/ " +
                   "卓から卓 " + _between.Count + " 本";
        }
    }
}
