using System;

namespace NavisworksTransport.Utils.CoordinateSystem
{
    public enum ObjectStartPlacementMode
    {
        AlignToPathPose = 0,
        PreserveInitialPose = 1
    }

    public struct ObjectStartPlacementRequest : IEquatable<ObjectStartPlacementRequest>
    {
        public static readonly ObjectStartPlacementRequest TranslationOnly =
            new ObjectStartPlacementRequest(LocalEulerRotationCorrection.Zero, ObjectStartPlacementMode.PreserveInitialPose, 0.0);

        public ObjectStartPlacementRequest(
            LocalEulerRotationCorrection rotationCorrection,
            ObjectStartPlacementMode placementMode,
            double verticalLiftInMeters)
        {
            RotationCorrection = rotationCorrection;
            PlacementMode = placementMode;
            VerticalLiftInMeters = verticalLiftInMeters;
        }

        public LocalEulerRotationCorrection RotationCorrection { get; }

        public ObjectStartPlacementMode PlacementMode { get; }

        public double VerticalLiftInMeters { get; }

        public bool PreserveInitialPose => PlacementMode == ObjectStartPlacementMode.PreserveInitialPose;

        public static ObjectStartPlacementRequest CreateRotationCorrection(
            LocalEulerRotationCorrection rotationCorrection,
            double verticalLiftInMeters = 0.0)
        {
            return new ObjectStartPlacementRequest(rotationCorrection, ObjectStartPlacementMode.AlignToPathPose, verticalLiftInMeters);
        }

        public static ObjectStartPlacementRequest CreateTranslationOnly(double verticalLiftInMeters = 0.0)
        {
            return new ObjectStartPlacementRequest(LocalEulerRotationCorrection.Zero, ObjectStartPlacementMode.PreserveInitialPose, verticalLiftInMeters);
        }

        public bool Equals(ObjectStartPlacementRequest other)
        {
            return RotationCorrection.Equals(other.RotationCorrection) &&
                   PlacementMode == other.PlacementMode &&
                   VerticalLiftInMeters.Equals(other.VerticalLiftInMeters);
        }

        public override bool Equals(object obj)
        {
            return obj is ObjectStartPlacementRequest other && Equals(other);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hashCode = RotationCorrection.GetHashCode();
                hashCode = (hashCode * 397) ^ (int)PlacementMode;
                hashCode = (hashCode * 397) ^ VerticalLiftInMeters.GetHashCode();
                return hashCode;
            }
        }

        public override string ToString()
        {
            return $"PlacementMode={PlacementMode}, Rotation={RotationCorrection}, VerticalLiftInMeters={VerticalLiftInMeters:F3}";
        }
    }
}
