﻿using System;
using System.Collections.Generic;

namespace Oni
{
    internal struct BoundingSphere : IEquatable<BoundingSphere>
    {
        public Vector3 Center;
        public float Radius;

        public BoundingSphere(Vector3 center, float radius)
        {
            Center = center;
            Radius = radius;
        }

        public static BoundingSphere CreateFromBoundingBox(BoundingBox bbox)
        {
            BoundingSphere r;
            r.Center = (bbox.Min + bbox.Max) * 0.5f;
            r.Radius = Vector3.Distance(r.Center, bbox.Min);
            return r;
        }

        public static BoundingSphere CreateFromPoints(IEnumerable<Vector3> points)
        {
            var center = Vector3.Zero;
            int count = 0;

            foreach (var point in points)
            {
                center += point;
                count++;
            }

            center /= count;

            float radius = 0.0f;

            foreach (var point in points)
            {
                float distance = Vector3.DistanceSquared(center, point);

                if (distance > radius)
                    radius = distance;
            }

            radius = FMath.Sqrt(radius);

            return new BoundingSphere(center, radius);
        }

        public static bool operator ==(BoundingSphere s1, BoundingSphere s2) => s1.Radius == s2.Radius && s1.Center == s2.Center;
        public static bool operator !=(BoundingSphere s1, BoundingSphere s2) => s1.Radius != s2.Radius || s1.Center != s2.Center;

        public bool Equals(BoundingSphere other) => other.Radius == Radius && other.Center == Center;

        public override bool Equals(object obj) => obj is BoundingSphere && Equals((BoundingSphere)obj);
        public override int GetHashCode() => Radius.GetHashCode() ^ Center.GetHashCode();

        public override string ToString() => $"{{{Center} {Radius}}}";
    }
}
