using Microsoft.VisualStudio.TestTools.UnitTesting;
using NavisworksTransport.Utils;
using System.Numerics;
using NavisworksTransport.Core.Config;

namespace NavisworksTransport.UnitTests.CoordinateSystem
{
    [TestClass]
    public class ViewpointHelperTests
    {
        [TestMethod]
        public void ResolvePathViewpointProfile_ShouldReturnExpectedDefaults()
        {
            var config = ConfigManager.Instance.Current.PathEditing;
            var ground = ViewpointHelper.ResolvePathViewpointProfile(ViewpointHelper.ViewpointStrategy.PathGroundSelection);
            var hoisting = ViewpointHelper.ResolvePathViewpointProfile(ViewpointHelper.ViewpointStrategy.PathHoistingSelection);
            var rail = ViewpointHelper.ResolvePathViewpointProfile(ViewpointHelper.ViewpointStrategy.PathRailSelection);

            Assert.AreEqual(12.0, ground.CameraDistanceMeters, 1e-9);
            Assert.AreEqual(90.0, ground.ElevationDegrees, 1e-9);

            Assert.AreEqual(config.HoistingViewDistanceMeters, hoisting.CameraDistanceMeters, 1e-9);
            Assert.AreEqual(config.HoistingViewElevationDegrees, hoisting.ElevationDegrees, 1e-9);
            Assert.AreEqual(ViewpointHelper.PathCameraHorizontalMode.Side, hoisting.HorizontalMode);

            Assert.AreEqual(config.RailViewDistanceMeters, rail.CameraDistanceMeters, 1e-9);
            Assert.AreEqual(config.RailViewElevationDegrees, rail.ElevationDegrees, 1e-9);
            Assert.AreEqual(ViewpointHelper.PathCameraHorizontalMode.Side, rail.HorizontalMode);
        }

        [TestMethod]
        public void ResolveCameraOffsetDirection_Hoisting_ShouldLookFromSideAndSlightlyAbove()
        {
            Vector3 hostUp = Vector3.UnitZ;
            Vector3 forward = Vector3.UnitX;
            var profile = ViewpointHelper.ResolvePathViewpointProfile(ViewpointHelper.ViewpointStrategy.PathHoistingSelection);

            Vector3 offset = ViewpointHelper.ResolveCameraOffsetDirection(profile, hostUp, forward);

            Assert.AreEqual(0.0f, offset.X, 1e-5f);
            Assert.IsTrue(offset.Y > 0.0f);
            Assert.IsTrue(offset.Z > 0.0f);
        }

        [TestMethod]
        public void ResolveCameraOffsetDirection_Rail_ShouldLookFromSideAndSlightlyAbove()
        {
            Vector3 hostUp = Vector3.UnitZ;
            Vector3 forward = Vector3.UnitX;
            var profile = ViewpointHelper.ResolvePathViewpointProfile(ViewpointHelper.ViewpointStrategy.PathRailSelection);

            Vector3 offset = ViewpointHelper.ResolveCameraOffsetDirection(profile, hostUp, forward);

            Assert.AreEqual(0.0f, offset.X, 1e-5f);
            Assert.IsTrue(offset.Y > 0.0f);
            Assert.IsTrue(offset.Z > 0.0f);
        }

        [TestMethod]
        public void ResolveHorizontalPathForward_ShouldFallbackWhenPathIsVertical()
        {
            Vector3 hostUp = Vector3.UnitZ;
            Vector3 rawVertical = Vector3.UnitZ;
            Vector3 fallback = Vector3.UnitY;

            Vector3 resolved = ViewpointHelper.ResolveHorizontalPathForward(rawVertical, hostUp, fallback);

            Assert.AreEqual(0.0f, resolved.Z, 1e-5f);
            Assert.AreEqual(1.0f, resolved.Y, 1e-5f);
        }

        [TestMethod]
        public void ResolveFocusViewpointProfile_ShouldCentralizeNamedFocusStrategies()
        {
            var modelFocus = ViewpointHelper.ResolveFocusViewpointProfile(ViewpointHelper.ViewpointStrategy.ModelFocus);
            var collision = ViewpointHelper.ResolveFocusViewpointProfile(ViewpointHelper.ViewpointStrategy.CollisionCloseUp);

            Assert.AreEqual(60.0, modelFocus.ViewAngleDegrees, 1e-9);
            Assert.AreEqual(0.25, modelFocus.TargetViewRatio, 1e-9);

            Assert.AreEqual(60.0, collision.ViewAngleDegrees, 1e-9);
            Assert.AreEqual(0.25, collision.TargetViewRatio, 1e-9);
        }
    }
}
