using System;
using System.Linq;
using System.Windows.Input;
using System.Windows.Media.Media3D;
using devDept.Eyeshot;
using devDept.Eyeshot.Control;
using devDept.Eyeshot.Entities;
using devDept.Geometry;
using WpfEngineeringSketch.Models.Scene;
using WpfEngineeringSketch.Rendering;
using WpfEngineeringSketch.ViewModels;

namespace WpfEngineeringSketch.Tools3D
{
    public class PlaceTool3D : I3DTool
    {
        public string Name => "Place";
        private SceneObject? _ghostObject;

        public void Activate(MainViewModel vm)
        {
            _ghostObject = new SceneObject
            {
                Type = vm.SelectedBlockType,
                Position = new System.Windows.Media.Media3D.Point3D(0, 0, 0),
            };
            vm.Objects.Add(_ghostObject);

            if (vm.SelectedBlockType == BlockType.CMUWall)
            {
                UpdateSmartIndicators(vm);
            }
        }

        public void Deactivate(MainViewModel vm)
        {
            if (_ghostObject != null)
            {
                vm.Objects.Remove(_ghostObject);
                _ghostObject = null;
            }
        }

        public void OnMouseDown(MainViewModel vm, Design design, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
            {
                var mousePos = e.GetPosition(design);
                var point = new System.Drawing.Point((int)mousePos.X, (int)mousePos.Y);

                // 0. Check for UI Indicator Click (CMU Wall smart placement)
                if (vm.SelectedBlockType == BlockType.CMUWall)
                {
                    var item = design.GetItemUnderMouseCursor(point);
                    if (item != null && item.Item is Entity entity)
                    {
                        var obj = SceneBinder.GetSceneObjectFromEntity(entity);
                        if (obj != null && obj.Type == BlockType.UIIndicator)
                        {
                            var wallPos = new System.Windows.Media.Media3D.Point3D(obj.Position.X, obj.Position.Y - 2, obj.Position.Z);
                            var newWall = new SceneObject
                            {
                                Type = BlockType.CMUWall,
                                Position = wallPos,
                            };
                                
                            var gridLine = vm.Objects.FirstOrDefault(o => o.Type == BlockType.GridLine && (o.Position - wallPos).Length < 0.1);
                            if (gridLine != null) newWall.Rotation = gridLine.Rotation;

                            vm.Objects.Add(newWall);
                            vm.Objects.Remove(obj);
                            
                            // Optimization: Update indicators
                            UpdateSmartIndicators(vm);
                            return; 
                        }
                    }
                }

                // Normal Place Logic
                if (_ghostObject != null)
                {
                    // Create concrete object
                    // We need current position. Calculated in OnMouseMove, or re-calc here.
                    // Recalculate for safety
                    
                    design.ScreenToPlane(point, Plane.XY, out devDept.Geometry.Point3D worldPoint);
                    
                    // Simple snap
                    double snap = 0.5;
                    double x = Math.Round(worldPoint.X / snap) * snap;
                    double z = Math.Round(worldPoint.Z / snap) * snap;
                    double y = 0; // Flat on ground usually
                    
                    double yOffset = GetYOffset(vm.SelectedBlockType);
                    y += yOffset;
                    
                    var newObj = new SceneObject
                    {
                        Type = _ghostObject.Type,
                        Position = new System.Windows.Media.Media3D.Point3D(x, y, z),
                        Rotation = _ghostObject.Rotation,
                        Scale = _ghostObject.Scale
                    };
                    vm.Objects.Add(newObj);
                }
            }
        }

        public void OnMouseMove(MainViewModel vm, Design design, MouseEventArgs e)
        {
            if (_ghostObject != null)
            {
                 var mousePos = e.GetPosition(design);
                 design.ScreenToPlane(new System.Drawing.Point((int)mousePos.X, (int)mousePos.Y), Plane.XY, out devDept.Geometry.Point3D worldPoint);
                 
                 if (worldPoint != null)
                 {
                    double snap = 0.5;
                    double x = Math.Round(worldPoint.X / snap) * snap;
                    double z = Math.Round(worldPoint.Z / snap) * snap;
                    double y = 0;
                    
                    double yOffset = GetYOffset(vm.SelectedBlockType);
                    y += yOffset;

                    _ghostObject.Position = new System.Windows.Media.Media3D.Point3D(x, y, z);
                    
                    if (_ghostObject.Type != vm.SelectedBlockType)
                    {
                        _ghostObject.Type = vm.SelectedBlockType;
                    }
                 }
            }
        }

        public void OnMouseUp(MainViewModel vm, Design design, MouseButtonEventArgs e) { }
        
        private double GetYOffset(BlockType type)
        {
             switch (type)
            {
                case BlockType.Cube: return 0.5;
                case BlockType.Column: return 1.5; 
                case BlockType.Cylinder: return 0.5; 
                case BlockType.Sphere: return 0.5;
                case BlockType.Beam: return 0.25; 
                case BlockType.CMUWall: return 1.5; 
                default: return 0;
            }
        }

        private void UpdateSmartIndicators(MainViewModel vm)
        {
            if (!vm.ShowSmartPlacementHints)
            {
                ClearSmartIndicators(vm);
                return;
            }

            bool hasIndicators = vm.Objects.Any(o => o.Type == BlockType.UIIndicator);
            if (!hasIndicators)
            {
                 var gridLines = vm.Objects.Where(o => o.Type == BlockType.GridLine).ToList();
                 var walls = vm.Objects.Where(o => o.Type == BlockType.CMUWall).ToList();
                 
                 foreach (var line in gridLines)
                 {
                     bool occupied = walls.Any(w => (w.Position - line.Position).Length < 0.1);
                     if (!occupied)
                     {
                         vm.Objects.Add(new SceneObject
                         {
                             Type = BlockType.UIIndicator,
                             Position = new System.Windows.Media.Media3D.Point3D(line.Position.X, line.Position.Y + 2, line.Position.Z),
                             Rotation = new System.Windows.Media.Media3D.Vector3D(0,0,0),
                             Scale = new System.Windows.Media.Media3D.Vector3D(1,1,1)
                         });
                     }
                 }
            }
        }
        
        private void ClearSmartIndicators(MainViewModel vm)
        {
            var indicators = vm.Objects.Where(o => o.Type == BlockType.UIIndicator).ToList();
            foreach (var ind in indicators)
            {
                vm.Objects.Remove(ind);
            }
        }
    }
}



