using System;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;

namespace Earthblend.Nts.Common.MeshGenerators.Base
{
    [RuntimeNameProperty("Name")]
    public abstract class MeshGeneratorBase : CustomBindableBase // Animatable
    {
        public static readonly DependencyProperty MovementValueProperty = DependencyProperty.Register("MovementValue", typeof(Double), typeof(MeshGeneratorBase), new PropertyMetadata(1.0D));

        public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(MeshGeneratorBase));
        public string Name { set { SetValue(NameProperty, value); } get { return (string)GetValue(NameProperty); }
        }

        static DependencyPropertyKey GeometryKey = DependencyProperty.RegisterReadOnly("Geometry",typeof(MeshGeometry3D),typeof(MeshGeneratorBase),new PropertyMetadata(new MeshGeometry3D()));

        public static readonly DependencyProperty GeometryProperty = GeometryKey.DependencyProperty;

        public MeshGeometry3D Geometry { set { SetValue(GeometryKey, value); } get { return (MeshGeometry3D)GetValue(GeometryProperty); } }
        public Double MovementValue { set { SetValue(MovementValueProperty, value); } get { return (Double)GetValue(MovementValueProperty); } }

        public MeshGeneratorBase()
        {
            Geometry = new MeshGeometry3D();
        }

        protected static void PropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            (obj as MeshGeneratorBase).PropertyChanged(args);
        }

        protected virtual void PropertyChanged(DependencyPropertyChangedEventArgs args)
        {
            // Get the MeshGeometry3D for local convenience.
            MeshGeometry3D mesh = Geometry;

            // Obtain the four collection of the MeshGeometry3D.
            Point3DCollection vertices = mesh.Positions;
            Vector3DCollection normals = mesh.Normals;
            Int32Collection indices = mesh.TriangleIndices;
            PointCollection textures = mesh.TextureCoordinates;

            // Set the MeshGeometry3D collections to null while updating.
            mesh.Positions = null;
            mesh.Normals = null;
            mesh.TriangleIndices = null;
            mesh.TextureCoordinates = null;

            // Call the abstract method to fill the collections.
            Triangulate(args, vertices, normals, indices, textures);

            // Set the updated collections to the MeshGeometry3D.
            mesh.TextureCoordinates = textures;
            mesh.TriangleIndices = indices;
            mesh.Normals = normals;
            mesh.Positions = vertices;
        }

        protected abstract void Triangulate(DependencyPropertyChangedEventArgs args,Point3DCollection vertices,Vector3DCollection normals,Int32Collection indices,PointCollection textures);
    }
}


