using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;

using Spark3D.Algebra3D;

namespace Spark3D.Objects3D.Shapes
{
    public class Sphere : Object3DCommon, IObject3D
    {
        public Sphere(double radius, int Ntesselations) : base(MakeFaces(radius, Ntesselations)) { }

        static IList<Polygon3D> MakeFaces(double r, int Ntesselations)
        {
            Octahedron oct = new Octahedron(2 * r);
            IList<Polygon3D> polygons = oct.itsPolygons;
            return RecurssiveTesselation(polygons, r, ref Ntesselations);
        }

        static IList<Polygon3D> RecurssiveTesselation(IList<Polygon3D> polygons, double r, ref int Ntesselations)
        {
            // Terminate recursion
            if (Ntesselations == 0) 
                return polygons;

            IList<Polygon3D> ret = new List<Polygon3D>();
            Vector3D[] midpoints = new Vector3D[3];
            foreach (Polygon3D p in polygons)
            {

                int Nvert = p.NumVerticies;
                for (int i = 0; i < Nvert; i++)
                {
                    Debug.Assert(Math.Abs(p.itsVerticies[i].Magnitude() - r) < 1e-6);
                    int i1 = (i + 1) % Nvert;
                    midpoints[i] = (p.itsVerticies[i1] + p.itsVerticies[i]) / 2.0;
                    midpoints[i] *= r / midpoints[i].Magnitude();
                }

                ret.Add(new Polygon3D(new Vector3D[] 
                {
                     p.itsVerticies[0],
                     midpoints[0],
                     midpoints[2]
                }, Color.DarkRed));

                ret.Add(new Polygon3D(new Vector3D[] 
                {
                     p.itsVerticies[1],
                     midpoints[0],
                     midpoints[1]
                }, Color.Blue));
                ret.Add(new Polygon3D(new Vector3D[] 
                {
                     p.itsVerticies[2],
                     midpoints[1],
                     midpoints[2]
                }, Color.Blue));
                ret.Add(new Polygon3D(new Vector3D[] 
                {
                     midpoints[0],
                     midpoints[1],
                     midpoints[2]
                }, Color.DarkRed));

            }
            Ntesselations--;
            return RecurssiveTesselation(ret, r, ref Ntesselations);
        }
    }
}
