using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
using System.Windows.Media;
using System.Windows;
using SurfacePlot3D.Statics;
using SurfacePlot3D.Members;

namespace SurfacePlot3D.MeshGenerators
{
    public class RibbonTextMeshGenerator : MeshGeneratorBase
    {
        public RibbonTextMeshGenerator() { PropertyChanged(new DependencyPropertyChangedEventArgs()); }

        public void GenerateMesh()
        {
            PropertyChanged(new DependencyPropertyChangedEventArgs());
        }

        public static IList<String> Properties = new List<String>() { "Text", "FontSize", "FontDepth" };

        public RibbonTextMeshGenerator Duplicate()
        {
            RibbonTextMeshGenerator meshGenerator = new RibbonTextMeshGenerator();

            meshGenerator.Text = Text;
            meshGenerator.FontSize = FontSize;
            meshGenerator.FontDepth = FontDepth;

            return meshGenerator;
        }

        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(String), typeof(RibbonTextMeshGenerator), new PropertyMetadata("Test", PropertyChanged));
        public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(1.0D, PropertyChanged));
        public static readonly DependencyProperty FontDepthProperty = DependencyProperty.Register("FontDepth", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(.5D, PropertyChanged));
        public static readonly DependencyProperty RotateXProperty = DependencyProperty.Register("RotateX", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));
        public static readonly DependencyProperty RotateYProperty = DependencyProperty.Register("RotateY", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));
        public static readonly DependencyProperty RotateZProperty = DependencyProperty.Register("RotateZ", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));

        public static readonly DependencyProperty TextOffsetXProperty = DependencyProperty.Register("TextOffsetX", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));
        public static readonly DependencyProperty TextOffsetYProperty = DependencyProperty.Register("TextOffsetY", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));
        public static readonly DependencyProperty TextOffsetZProperty = DependencyProperty.Register("TextOffsetZ", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));

        public static readonly DependencyProperty PosXProperty = DependencyProperty.Register("PosX", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));
        public static readonly DependencyProperty PosYProperty = DependencyProperty.Register("PosY", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));
        public static readonly DependencyProperty PosZProperty = DependencyProperty.Register("PosZ", typeof(Double), typeof(RibbonTextMeshGenerator), new PropertyMetadata(0.0D, PropertyChanged));


        public Double PosX { set { SetValue(PosXProperty, value); } get { return (Double)GetValue(PosXProperty); } }
        public Double PosY { set { SetValue(PosYProperty, value); } get { return (Double)GetValue(PosYProperty); } }
        public Double PosZ { set { SetValue(PosZProperty, value); } get { return (Double)GetValue(PosZProperty); } }

        public Double TextOffsetX { set { SetValue(TextOffsetXProperty, value); } get { return (Double)GetValue(TextOffsetXProperty); } }
        public Double TextOffsetY { set { SetValue(TextOffsetYProperty, value); } get { return (Double)GetValue(TextOffsetYProperty); } }
        public Double TextOffsetZ { set { SetValue(TextOffsetZProperty, value); } get { return (Double)GetValue(TextOffsetZProperty); } }


        public Double RotateX { set { SetValue(RotateXProperty, value); } get { return (Double)GetValue(RotateXProperty); } }
        public Double RotateY { set { SetValue(RotateYProperty, value); } get { return (Double)GetValue(RotateYProperty); } }
        public Double RotateZ { set { SetValue(RotateZProperty, value); } get { return (Double)GetValue(RotateZProperty); } }

        public String Text { set { SetValue(TextProperty, value); } get { return (String)GetValue(TextProperty); } }
        public Double FontSize { set { SetValue(FontSizeProperty, value); } get { return (Double)GetValue(FontSizeProperty); } }
        public Double FontDepth { set { SetValue(FontDepthProperty, value); } get { return (Double)GetValue(FontDepthProperty); } }

        protected override void Triangulate(DependencyPropertyChangedEventArgs args, Point3DCollection vertices, Vector3DCollection normals, Int32Collection indices, PointCollection textures)
        {
            vertices.Clear(); normals.Clear(); indices.Clear(); textures.Clear();

            RibbonText ribbonText = new RibbonText() { Text = Text, FontSize = FontSize, Depth = FontDepth };

            vertices = ribbonText.Mesh3D.Positions;
            indices = ribbonText.Mesh3D.TriangleIndices;
            textures = ribbonText.Mesh3D.TextureCoordinates;

            var mesh = new MeshGeometry3D();
            if (vertices.Any())
            {
                var centroid = new Point3D(vertices.Average(p => p.X), vertices.Average(p => p.Y), vertices.Average(p => p.Z));
                foreach (var p in vertices)
                {
                    mesh.Positions.Add(new Point3D(p.X - centroid.X, p.Y - centroid.Y, p.Z - centroid.Z));
                }
            }

            Point3DCollection pc = mesh.Positions;

            mesh.Positions = ObjectUtil.RotateObjectByAxis(pc, "X", RotateX, new Point3D(0, 0, 0));
            mesh.Positions = ObjectUtil.RotateObjectByAxis(mesh.Positions, "Y", RotateY, new Point3D(0, 0, 0));
            mesh.Positions = ObjectUtil.RotateObjectByAxis(mesh.Positions, "Z", RotateZ, new Point3D(0, 0, 0));

            for (int i = 0; i < mesh.Positions.Count; i++)
            {
                mesh.Positions[i] = new Point3D(mesh.Positions[i].X, mesh.Positions[i].Y, mesh.Positions[i].Z);
                //mesh.Positions[i] = new Point3D(mesh.Positions[i].X + TextOffsetX + PosX, mesh.Positions[i].Y + TextOffsetY + PosY, mesh.Positions[i].Z + TextOffsetZ + PosZ);
            }


            Geometry = new MeshGeometry3D() { Positions = mesh.Positions, Normals = normals, TriangleIndices = indices, TextureCoordinates = textures };

            ribbonText = null;
        }



        /// <summary>
        /// Will use later
        /// </summary>
        /// <param name="verticies"></param>
        /// <returns></returns>
        //public Point3D CalculateCentroid(List<Point3D> verticies)
        //{
        //    var s = new Vector3D();
        //    var areaTotal = 0.0;

        //    var p1 = verticies[0];
        //    var p2 = verticies[1];

        //    for (var i = 2; i < verticies.Count; i++)
        //    {
        //        var p3 = verticies[i];
        //        var edge1 = p3 - p1;
        //        var edge2 = p3 - p2;

        //        var crossProduct = Vector3D.CrossProduct(edge1, edge2);
        //        var area = crossProduct.Length / 2;

        //        s.X += area * (p1.X + p2.X + p3.X) / 3;
        //        s.Y += area * (p1.Y + p2.Y + p3.Y) / 3;
        //        s.Z += area * (p1.Z + p2.Z + p3.Z) / 3;

        //        areaTotal += area;
        //        p2 = p3;
        //    }

        //    var point = new Point3D
        //    {
        //        X = s.X / areaTotal,
        //        Y = s.Y / areaTotal,
        //        Z = s.Z / areaTotal
        //    };


        //    return point;
        //}
    }
}
