using GeoSus.Client;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;


namespace Subsystems{
    [System.Serializable]
    public class BuildingSettings
    {
        public Material ResidentalBuildingsMat;
        public float ResidentalBuildingHeight;
        public Material CommercialBuildingsMat;
        public float CommercialBuildingHeight;
        public Material IndustrialBuildingsMat;
        public float IndustrialBuildingHeight;
        public Material DefaultBuildingMat;
        public float DefaultBuildingHeight;
    }
    [System.Serializable]
    public class PathwaySettings
    {
        public Material FootwayMat;
        public float FootwayWidth;
        public Material PathMat;
        public float PathWidth;
        public Material StepsMat;
        public float StepsWidth;
        public Material CyclewayMat;
        public float CyclewayWidth;
        public Material PedestrianMat;
        public float PedestrianWidth;
        public Material RoadMat;
        public float RoadWidth;
        public Material ServiceMat;
        public float ServiceWidth;
        public Material ResidentialMat;
        public float ResidentialWidth;
        public Material TrackMat;
        public float TrackWidth;
        public Material DefaultMat;
        public float DefaultWidth;
    }
    [System.Serializable]
    public class AreaSettings
    {
        public Material ParkMat;
        public Material GardenMat;
        public Material PlaygroundMat;
        public Material ForestMat;
        public Material GrassMat;
        public Material WaterMat;
        public Material DefaultMat;
    }
    public class GameManager_Map
    {
        private GameClient _gameClient;
        private GameObject _mapCenterPoint;
        private Position _centerPosition;
        private BuildingSettings _buildingSettings;
        private PathwaySettings _pathwaySettings;
        private AreaSettings _areaSettings;
        private const float _metersPerUnit = 1f; 
        public GameManager_Map(GameClient gameClient, GameObject mapCenterPoint, BuildingSettings buildingSettings, PathwaySettings pathwaySettings, AreaSettings areaSettings)
        {
            _gameClient = gameClient;
            _mapCenterPoint = mapCenterPoint;
            _buildingSettings = buildingSettings;
            _pathwaySettings = pathwaySettings;
            _areaSettings = areaSettings;
        }
        public void BuildMap()
        {
            ClearChildren();
            _centerPosition = _gameClient.CurrentLobbyState.MapData.Center;
            GameObject buildingsRoot = new GameObject("Buildings");
            buildingsRoot.transform.parent = _mapCenterPoint.transform;

            GameObject pathRoot = new GameObject("Pathways");
            pathRoot.transform.parent = _mapCenterPoint.transform;

            GameObject areaRoot = new GameObject("Areas");
            areaRoot.transform.parent = _mapCenterPoint.transform;

            foreach (var building in _gameClient.CurrentLobbyState.MapData.GetBuildings())
            {
                string buildingType = "Unknown";
                try
                {
                    buildingType = _gameClient.CurrentLobbyState.MapData.BuildingTypes[_gameClient.CurrentLobbyState.MapData.GetBuildings().IndexOf(building)];
                }
                catch (Exception ex) { Debug.Log($"Error: {ex.Message}"); }
                building.Name = buildingType;
                GameObject b = BuildBuildingMesh(building);
                b.transform.parent = buildingsRoot.transform;
            }
            foreach (var path in _gameClient.CurrentLobbyState.MapData.GetPathways())
            {
                GameObject p = BuildPathwayMesh(path);
                p.transform.parent = pathRoot.transform;
            }
            foreach (var area in _gameClient.CurrentLobbyState.MapData.GetAreas())
            {
                GameObject a = BuildAreaMesh(area);
                a.transform.parent = areaRoot.transform;
            }
            //TODO: POIs
        }
        void ClearChildren()
        {
            List<GameObject> toDestroy = new List<GameObject>();
            foreach (Transform t in _mapCenterPoint.transform)
                toDestroy.Add(t.gameObject);
            foreach (var g in toDestroy)
            {
                UnityEngine.Object.DestroyImmediate(g);
            }
        }
        #region Mesh Building
        GameObject BuildBuildingMesh(MapBuilding b)
        {
            var building = new GameObject($"Building_{b.Name ?? "Unknown"}");

            // Výpočet středu budovy
            Vector3 center = CalculatePolygonCenter(b.Outline);
            building.transform.position = center;

            // Vytvoření mesh pro budovu
            MeshFilter meshFilter = building.AddComponent<MeshFilter>();
            MeshRenderer meshRenderer = building.AddComponent<MeshRenderer>();

            float height;
            Material mat;
            switch (b.BuildingType.ToLower())
            {
                case "residential":
                    mat = _buildingSettings.ResidentalBuildingsMat;
                    height = _buildingSettings.ResidentalBuildingHeight;
                    break;
                case "commercial":
                    mat = _buildingSettings.CommercialBuildingsMat;
                    height = _buildingSettings.CommercialBuildingHeight;
                    break;
                case "industrial":
                    mat = _buildingSettings.IndustrialBuildingsMat;
                    height = _buildingSettings.IndustrialBuildingHeight;
                    break;
                default:
                    mat = _buildingSettings.DefaultBuildingMat;
                    height = _buildingSettings.DefaultBuildingHeight;
                    break;
            }
            Mesh mesh = CreateExtrudedPolygonMesh(b.Outline, height);
            meshFilter.mesh = mesh;

            //TODO: material by type
            // Použijeme barvu podle typu budovy
            meshRenderer.material = mat;

            // Přidání collideru pro interakci
            building.AddComponent<MeshCollider>();
            return building;
        }
        GameObject BuildPathwayMesh(MapPathway w)
        {
            var path = new GameObject($"Path_{w.Name ?? "Unknown"}");

            // Použijeme LineRenderer pro jednoduchost
            LineRenderer line = path.AddComponent<LineRenderer>();
            float width;
            Material mat;
            
            switch (w.PathType)
            {
                case PathType.Footway:
                    mat = _pathwaySettings.FootwayMat;
                    width = _pathwaySettings.FootwayWidth;
                    break;
                case PathType.Path:
                    mat = _pathwaySettings.PathMat;
                    width = _pathwaySettings.PathWidth;
                    break;
                case PathType.Steps:
                    mat = _pathwaySettings.StepsMat;
                    width = _pathwaySettings.PathWidth;
                    break;
                case PathType.Cycleway:
                    mat = _pathwaySettings.CyclewayMat;
                    width = _pathwaySettings.CyclewayWidth;
                    break;
                case PathType.Pedestrian:
                    mat = _pathwaySettings.PedestrianMat;
                    width = _pathwaySettings.PedestrianWidth;
                    break;
                case PathType.Road:
                    mat = _pathwaySettings.RoadMat;
                    width = _pathwaySettings.RoadWidth;
                    break;
                case PathType.Service:
                    mat = _pathwaySettings.ServiceMat;
                    width = _pathwaySettings.ServiceWidth;
                    break;
                case PathType.Residential:
                    mat = _pathwaySettings.ResidentialMat;
                    width = _pathwaySettings.ResidentialWidth;
                    break;
                case PathType.Track:
                    mat = _pathwaySettings.TrackMat;
                    width = _pathwaySettings.TrackWidth;
                    break;
                default:
                    mat = _pathwaySettings.DefaultMat;
                    width = _pathwaySettings.DefaultWidth;
                    break;
            }

            line.material = mat;
            line.widthMultiplier = width;

            // Nastavení bodů cesty
            line.positionCount = w.Points.Count;
            for (int i = 0; i < w.Points.Count; i++)
            {
                Vector3 pos = w.Points[i].ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center);
                pos.y = 0.1f; // Mírně nad zemí
                line.SetPosition(i, pos);
            }
            return path;
        }
        GameObject BuildAreaMesh(MapArea a)
        {
            var area = new GameObject($"Area_{a.Name ?? "Unknown"}");

            MeshFilter meshFilter = area.AddComponent<MeshFilter>();
            MeshRenderer meshRenderer = area.AddComponent<MeshRenderer>();

            // Vytvoření plochého mesh
            Mesh mesh = CreateFlatPolygonMesh(a.Outline);
            meshFilter.mesh = mesh;

            
            Material mat;
            switch (a.AreaType)
            {
                case MapAreaType.Park:
                    mat = _areaSettings.ParkMat;
                    break;
                case MapAreaType.Garden:
                    mat = _areaSettings.GardenMat;
                    break;
                case MapAreaType.Playground:
                    mat = _areaSettings.PlaygroundMat;
                    break;
                case MapAreaType.Forest:
                    mat = _areaSettings.ForestMat;
                    break;
                case MapAreaType.Grass:
                    mat = _areaSettings.GrassMat;
                    break;
                case MapAreaType.Water:
                    mat = _areaSettings.WaterMat;
                    break;
                default:
                    mat = _areaSettings.DefaultMat;
                    break;
            }
            
            meshRenderer.material = mat;

            area.transform.position = new Vector3(0, 0.05f, 0); // Těsně nad zemí

            return area;
        }
        //TODO: POIs
        #endregion
        #region Polygon Utils
        private Vector3 CalculatePolygonCenter(List<Position> points)
        {
            Vector3 center = Vector3.zero;
            foreach (var point in points)
            {
                center += point.ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center);
            }
            return center / points.Count;
        }
        private Mesh CreateExtrudedPolygonMesh(List<Position> outline, float height)
        {
            Mesh mesh = new Mesh();

            int vertexCount = outline.Count;

            // Vertices - spodní a horní podstava
            Vector3[] vertices = new Vector3[vertexCount * 2];
            Vector3 center = CalculatePolygonCenter(outline);

            for (int i = 0; i < vertexCount; i++)
            {
                Vector3 pos = outline[i].ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center) - center;
                vertices[i] = pos; // Spodní
                vertices[i + vertexCount] = pos + Vector3.up * height; // Horní
            }

            // Triangles - jen boční stěny pro jednoduchost
            List<int> triangles = new List<int>();

            for (int i = 0; i < vertexCount; i++)
            {
                int next = (i + 1) % vertexCount;

                // Boční stěna - dva trojúhelníky
                triangles.Add(i);
                triangles.Add(i + vertexCount);
                triangles.Add(next);

                triangles.Add(next);
                triangles.Add(i + vertexCount);
                triangles.Add(next + vertexCount);
            }

            // Horní podstava - zjednodušená triangulace (fan)
            if (vertexCount >= 3)
            {
                for (int i = 1; i < vertexCount - 1; i++)
                {
                    triangles.Add(vertexCount); // Střed (první bod horní)
                    triangles.Add(vertexCount + i);
                    triangles.Add(vertexCount + i + 1);
                }
            }

            mesh.vertices = vertices;
            mesh.triangles = triangles.ToArray();
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            return mesh;
        }
        private Mesh CreateFlatPolygonMesh(List<Position> outline)
        {
            Mesh mesh = new Mesh();

            int vertexCount = outline.Count;
            Vector3[] vertices = new Vector3[vertexCount];
            Vector3 center = CalculatePolygonCenter(outline);

            for (int i = 0; i < vertexCount; i++)
            {
                vertices[i] = outline[i].ToLocalVector3(_gameClient.CurrentLobbyState.MapData.Center) - center;
            }

            // Triangulace - fan pattern
            List<int> triangles = new List<int>();
            if (vertexCount >= 3)
            {
                for (int i = 1; i < vertexCount - 1; i++)
                {
                    triangles.Add(0);
                    triangles.Add(i);
                    triangles.Add(i + 1);
                }
            }

            mesh.vertices = vertices;
            mesh.triangles = triangles.ToArray();
            mesh.RecalculateNormals();

            return mesh;
        }
        #endregion
    }
}
