using Earthblend.Tts.Common.Core.MeshGenerators.Base;
using Earthblend.Tts.Common.Core.Enumerations;
using Earthblend.Tts.Common.Core.Interfaces;
using Earthblend.Tts.Common.Core.Members;
using Earthblend.Tts.Shell.Interfaces;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Media.Media3D;
using System.Xml.Serialization;
using Earthblend.Nts.Common.MeshGenerators;
using Earthblend.Tts.Common.Core.MeshGenerators;
using Earthblend.Tts.Common.MeshGenerators;
using Earthblend.Tts.Common.Core.Services;
using Earthblend.Tts.Common.Core.Statics;
using VirtualCanvasTestCode.MeshGenerators;

namespace Earthblend.Tts.Common.Core.Members
{
    [Serializable]
    public class VirtualWorld3DPluginDataItem : DataItem3D, IPluginDataItem, IText, IReference
    {
        #region Private Variables

        private int _constructionSequence = 0;
        private int _level = 0;
        private int _sequence = 0;

        private Boolean _mirrorText = false;
        private Boolean _augment = false;
        private Boolean _marker = false;
        private Boolean _showArrow = false;
        private Boolean _autoCenter = false;
        private Boolean _isGroup = false;
        private Boolean _isExpanded = false;
        private Boolean _isSelected = false;
        private Boolean _isVirtual = false;

        private Double _textFontSize = 1;
        private Double _price = 0.0D;

        private Double _textOffsetPosX = 0.0D;
        private Double _textOffsetPosY = 0.0D;
        private Double _textOffsetPosZ = 0.0D;

        private Double _rotateX = 0.0D;
        private Double _rotateY = 0.0D;
        private Double _rotateZ = 0.0D;

        private Double _arrowRotationX = 0.0D;
        private Double _arrowRotationY = 0.0D;
        private Double _arrowRotationZ = 0.0D;

        private Double _arrowOffsetX = 0.0D;
        private Double _arrowOffsetY = 0.0D;
        private Double _arrowOffsetZ = 0.0D;

        private Boolean _renderLabel = true;
        private Boolean _useFrontMaterialAsBackMaterial = false;

        private Double _arrowPoint1X = 0.0D;
        private Double _arrowPoint1Y = -.25D;
        private Double _arrowPoint1Z = 0.0D;

        private Double _arrowPoint2X = 0.0D;
        private Double _arrowPoint2Y = .25D;
        private Double _arrowPoint2Z = 0.0D;

        private Double _textRotationX = 90.0D;
        private Double _textRotationY = 0.0D;
        private Double _textRotationZ = 180.0D;
        private Double _fontDepth = .5D;

        private Double _ttx = 0.0D;
        private Double _tty = 0.0D;
        private Double _ttz = 0.0D;

        private Double _stx = 1.0D;
        private Double _sty = 1.0D;
        private Double _stz = 1.0D;

        private Double _ctx = 0.0D;
        private Double _cty = 0.0D;
        private Double _ctz = 0.0D;

        private Double _rtx = 0.0D;
        private Double _rty = 0.0D;
        private Double _rtz = 0.0D;

        private String _assembly = String.Empty;
        private String _name = String.Empty;
        private String _hierarchyName = String.Empty;
        private String _text = String.Empty;
        private String _textUom = String.Empty;
        private String _textBrush = "White";
        private String _variableName = String.Empty;
        private String _className = String.Empty;

        private Guid _textLinked3DObjectId = Guid.Empty;
        private Guid _arrowLinked3DObjectId = Guid.Empty;
        private Guid _tagId = Guid.Empty;
        private Guid _nodeId = Guid.Empty;
        private Guid _parentId = Guid.Empty;

        private Vector3D _axisX = new Vector3D(1, 0, 0);
        private Vector3D _axisY = new Vector3D(0, 1, 0);
        private Vector3D _axisZ = new Vector3D(0, 0, 1);

        private WorldNodeType _nodeType = WorldNodeType.Object;
        private MathSymbolType _symbol = MathSymbolType.Unknown;
        private DropDataOrigin _origin = DropDataOrigin.Default;
        private ParameterType _pt = ParameterType.None;
        private ParameterFlow _pf = ParameterFlow.None;

        private GeometryModel3D _geometryModel3DReference = null;
        private Model3DGroup _objectModel3DGroup = null;
        private VirtualWorld3DPluginDataItem _parentNode = null;
        private GeometryModel3D _model = null;
        private Transform3DGroup _transformGroup = null;

        private ObservableCollection<VirtualWorld3DPluginDataItem> _childNodes = null;

        #endregion

        #region Public Clr Igonred Properties

        [XmlIgnore] public Model3DGroup ObjectModel3DGroup { get { return _objectModel3DGroup; } set { SetProperty(ref _objectModel3DGroup, value); } }
        [XmlIgnore] public VirtualWorld3DPluginDataItem ParentNode { get { return _parentNode; } set { SetProperty(ref _parentNode, value); } }
        [XmlIgnore] public GeometryModel3D GeometryModel3DReference { get { return _geometryModel3DReference; } set { SetProperty(ref _geometryModel3DReference, value); } }
        [XmlIgnore] public Transform3DGroup TransformGroup { get { return _transformGroup; } set { SetProperty(ref _transformGroup, value); } }
        [XmlIgnore] public Type ActualType { get { return Shape.GetType(); } }
        [XmlIgnore] public GeometryModel3D Model { get { return _model; } set { SetProperty(ref _model, value); } }
        [XmlIgnore] public Object ShapeObj { get { return Shape; } }
        [XmlIgnore] public Guid TextLinked3DObjectId { get { return _textLinked3DObjectId; } set { SetProperty(ref _textLinked3DObjectId, value); } }
        [XmlIgnore] public Guid ArrowLinked3DObjectId { get { return _arrowLinked3DObjectId; } set { SetProperty(ref _arrowLinked3DObjectId, value); } }

        #endregion


        #region Public Clr Properties

        public String ClassName { get { return _className; } set { SetProperty(ref _className, value); } }

        public int Level { get { return _level; } set { SetProperty(ref _level, value); } }
        public int Sequence { get { return _sequence; } set { SetProperty(ref _sequence, value); } }
        public int ConstructionSequence { get { return _constructionSequence; } set { SetProperty(ref _constructionSequence, value); } }

        public Boolean ShowArrow { get { return _showArrow; } set { SetProperty(ref _showArrow, value); } }
        public Boolean IsVirtual { get { return _isVirtual; } set { SetProperty(ref _isVirtual, value); } }
        public Boolean AutoCenter { get { return _autoCenter; } set { SetProperty(ref _autoCenter, value); } }
        public Boolean IsGroup { get { return _isGroup; } set { SetProperty(ref _isGroup, value); } }
        public Boolean IsExpanded { get { return _isExpanded; } set { SetProperty(ref _isExpanded, value); } }
        public Boolean IsSelected { get { return _isSelected; } set { SetProperty(ref _isSelected, value); } }
        public Boolean MirrorText { get { return _mirrorText; } set { SetProperty(ref _mirrorText, value); } }

        public Boolean UseFrontMaterialAsBackMaterial { get { return _useFrontMaterialAsBackMaterial; } set { SetProperty(ref _useFrontMaterialAsBackMaterial, value); } }
        public Boolean Marker { get { return _marker; } set { SetProperty(ref _marker, value); } }
        public Boolean Augment { get { return _augment; } set { SetProperty(ref _augment, value); } }

        public Double Ttx { get { return _ttx; } set { SetProperty(ref _ttx, value); } }
        public Double Tty { get { return _tty; } set { SetProperty(ref _tty, value); } }
        public Double Ttz { get { return _ttz; } set { SetProperty(ref _ttz, value); } }

        public Double Stx { get { return _stx; } set { SetProperty(ref _stx, value); } }
        public Double Sty { get { return _sty; } set { SetProperty(ref _sty, value); } }
        public Double Stz { get { return _stz; } set { SetProperty(ref _stz, value); } }
        public Double Ctx { get { return _ctx; } set { SetProperty(ref _ctx, value); } }
        public Double Cty { get { return _cty; } set { SetProperty(ref _cty, value); } }
        public Double Ctz { get { return _ctz; } set { SetProperty(ref _ctz, value); } }


        public Double Rtx { get { return _rtx; } set { SetProperty(ref _rtx, value); } }
        public Double Rty { get { return _rty; } set { SetProperty(ref _rty, value); } }
        public Double Rtz { get { return _rtz; } set { SetProperty(ref _rtz, value); } }

        public Double ArrowPoint1X { get { return _arrowPoint1X; } set { SetProperty(ref _arrowPoint1X, value); } }
        public Double ArrowPoint1Y { get { return _arrowPoint1Y; } set { SetProperty(ref _arrowPoint1Y, value); } }
        public Double ArrowPoint1Z { get { return _arrowPoint1Z; } set { SetProperty(ref _arrowPoint1Z, value); } }

        public Double ArrowPoint2X { get { return _arrowPoint2X; } set { SetProperty(ref _arrowPoint2X, value); } }
        public Double ArrowPoint2Y { get { return _arrowPoint2Y; } set { SetProperty(ref _arrowPoint2Y, value); } }
        public Double ArrowPoint2Z { get { return _arrowPoint2Z; } set { SetProperty(ref _arrowPoint2Z, value); } }

        public Boolean RenderLabel { get { return _renderLabel; } set { SetProperty(ref _renderLabel, value); } }

        public Double ArrowOffsetX { get { return _arrowOffsetX; } set { SetProperty(ref _arrowOffsetX, value); } }
        public Double ArrowOffsetY { get { return _arrowOffsetY; } set { SetProperty(ref _arrowOffsetY, value); } }
        public Double ArrowOffsetZ { get { return _arrowOffsetZ; } set { SetProperty(ref _arrowOffsetZ, value); } }

        public Double ArrowRotationX { get { return _arrowRotationX; } set { SetProperty(ref _arrowRotationX, value); } }
        public Double ArrowRotationY { get { return _arrowRotationY; } set { SetProperty(ref _arrowRotationY, value); } }
        public Double ArrowRotationZ { get { return _arrowRotationZ; } set { SetProperty(ref _arrowRotationZ, value); } }

        public Double TextOffsetPosX { get { return _textOffsetPosX; } set { SetProperty(ref _textOffsetPosX, value); } }
        public Double TextOffsetPosY { get { return _textOffsetPosY; } set { SetProperty(ref _textOffsetPosY, value); } }
        public Double TextOffsetPosZ { get { return _textOffsetPosZ; } set { SetProperty(ref _textOffsetPosZ, value); } }

        public Double TextRotationX { get { return _textRotationX; } set { SetProperty(ref _textRotationX, value); } }
        public Double TextRotationY { get { return _textRotationY; } set { SetProperty(ref _textRotationY, value); } }
        public Double TextRotationZ { get { return _textRotationZ; } set { SetProperty(ref _textRotationZ, value); } }

        public Double Price { get { return _price; } set { SetProperty(ref _price, value); } }

        public Double RotateX { get { return _rotateX; } set { SetProperty(ref _rotateX, value); } }
        public Double RotateY { get { return _rotateY; } set { SetProperty(ref _rotateY, value); } }
        public Double RotateZ { get { return _rotateZ; } set { SetProperty(ref _rotateZ, value); } }

        public Double FontDepth { get { return _fontDepth; } set { SetProperty(ref _fontDepth, value); } }
        public Double TextFontSize { get { return _textFontSize; } set { SetProperty(ref _textFontSize, value); } }


        public Guid NodeId { get { return _nodeId; } set { SetProperty(ref _nodeId, value); } }
        public Guid TabId { get { return _tagId; } set { SetProperty(ref _tagId, value); } }


        public Vector3D AxisX { get { return _axisX; } set { SetProperty(ref _axisX, value); } }
        public Vector3D AxisY { get { return _axisY; } set { SetProperty(ref _axisY, value); } }
        public Vector3D AxisZ { get { return _axisZ; } set { SetProperty(ref _axisZ, value); } }

        public String HierarchyName { get { return _hierarchyName; } set { SetProperty(ref _hierarchyName, value); } }
        public String Assembly { get { return _assembly; } set { SetProperty(ref _assembly, value); } }
        public String VariableName { get { return _variableName; } set { SetProperty(ref _variableName, value); } }
        public String TextBrush { get { return _textBrush; } set { SetProperty(ref _textBrush, value); } }
        public String Name { get { return _name; } set { SetProperty(ref _name, value); } }
        public String Text { get { return _text; } set { SetProperty(ref _text, value); } }
        public String TextUom { get { return _textUom; } set { SetProperty(ref _textUom, value); } }

        public Guid ParentId { get { return _parentId; } set { SetProperty(ref _parentId, value); } }

        public WorldNodeType NodeType { get { return _nodeType; } set { SetProperty(ref _nodeType, value); } }
        public MathSymbolType Symbol { get { return _symbol; } set { SetProperty(ref _symbol, value); } }
        public DropDataOrigin Origin { get { return _origin; } set { SetProperty(ref _origin, value); } }
        public ParameterFlow Pf { get { return _pf; } set { SetProperty(ref _pf, value); } }
        public ParameterType Pt { get { return _pt; } set { SetProperty(ref _pt, value); } }

        #endregion

        #region Public Clr  Collection Properties

        public ObservableCollection<VirtualWorld3DPluginDataItem> ChildNodes
        {
            get
            {
                if (this._childNodes == null) this._childNodes = new ObservableCollection<VirtualWorld3DPluginDataItem>();

                return this._childNodes;
            }
            set
            {
                if (_childNodes == value) return;
                SetProperty(ref _childNodes, value);
            }
        }

        #endregion

        #region Methods

        public void SetIsSelectedSilently(Boolean isSelected)
        {
            _isSelected = isSelected;
        }

        public void DuplicateShape(VirtualWorld3DPluginDataItem dataItem)
        {
            if (Shape != null)
            {
                if (Shape.GetType() == typeof(ArrowMeshGenerator)) dataItem.Shape = (Shape as ArrowMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(BoxMeshGenerator)) dataItem.Shape = (Shape as BoxMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(SkewBoxMeshGenerator)) dataItem.Shape = (Shape as SkewBoxMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(ConeMeshGenerator)) dataItem.Shape = (Shape as ConeMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(CylinderMeshGenerator)) dataItem.Shape = (Shape as CylinderMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(EllipsoidMeshGenerator)) dataItem.Shape = (Shape as EllipsoidMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(HollowCylinderMeshGenerator)) dataItem.Shape = (Shape as HollowCylinderMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(TubeMeshGenerator)) dataItem.Shape = (Shape as TubeMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(DodecahedronMeshGenerator)) dataItem.Shape = (Shape as DodecahedronMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(IcosahedronMeshGenerator)) dataItem.Shape = (Shape as IcosahedronMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(OctahedronMeshGenerator)) dataItem.Shape = (Shape as OctahedronMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(TetrahedronMeshGenerator)) dataItem.Shape = (Shape as TetrahedronMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(SphereMeshGenerator)) dataItem.Shape = (Shape as SphereMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(TorusMeshGenerator)) dataItem.Shape = (Shape as TorusMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(RibbonTextMeshGenerator)) dataItem.Shape = (Shape as RibbonTextMeshGenerator).Duplicate();
                else if (Shape.GetType() == typeof(WedgeMeshGenerator)) dataItem.Shape = (Shape as WedgeMeshGenerator).Duplicate();
            }
        }

        public VirtualWorld3DPluginDataItem DuplicateDataItem(Boolean ignoreParent = false)
        {
            VirtualWorld3DPluginDataItem dataItem = new VirtualWorld3DPluginDataItem();

            dataItem.Id = Guid.NewGuid();

            dataItem.TabId = TabId;
            dataItem.Sequence = Sequence;
            dataItem.Origin = Origin;
            dataItem.MirrorText = MirrorText;
            dataItem.HierarchyName = HierarchyName;

            dataItem.NodeType = NodeType;
            dataItem.NodeId = Guid.NewGuid();

            dataItem.MeshType = MeshType;
            dataItem.MeshColor = MeshColor;
            dataItem.ImagePath = ImagePath;
            dataItem.ImageName = ImageName;
            dataItem.BrushType = BrushType;
            dataItem.ConstructionSequence = ConstructionSequence;

            dataItem.RenderLabel = RenderLabel;
            dataItem.Level = Level;
            dataItem.HierarchyName = HierarchyName;

            dataItem.Ttx = Ttx;
            dataItem.Tty = Tty;
            dataItem.Ttz = Ttz;

            dataItem.Rtx = Rtx;
            dataItem.Rty = Rty;
            dataItem.Rtz = Rtz;

            dataItem.Group = Group;
            dataItem.Assembly = Assembly;

            dataItem.IsGroup = IsGroup;
            dataItem.AutoCenter = AutoCenter;

            dataItem.PosX = PosX;
            dataItem.PosY = PosY;
            dataItem.PosZ = PosZ;

            //dataItem.Connections = Connections;
            dataItem.Augment = Augment;
            dataItem.Assembly = Assembly;
            dataItem.Name = Name;
            dataItem.Text = Text;
            dataItem.TextUom = TextUom;
            dataItem.TextFontSize = TextFontSize;
            dataItem.FontDepth = FontDepth;
            dataItem.Price = Price;
            dataItem.TextOffsetPosX = TextOffsetPosX;
            dataItem.TextOffsetPosY = TextOffsetPosY;
            dataItem.TextOffsetPosZ = TextOffsetPosZ;

            dataItem.TextOffsetPosX = TextOffsetPosX;
            dataItem.TextOffsetPosY = TextOffsetPosY;
            dataItem.TextOffsetPosZ = TextOffsetPosZ;

            if (ignoreParent == false) dataItem.ParentId = ParentId;

            dataItem.Pt = Pt;
            dataItem.Pf = Pf;
            dataItem.TextBrush = TextBrush;

            dataItem.TextRotationX = TextRotationX;
            dataItem.TextRotationY = TextRotationY;
            dataItem.TextRotationZ = TextRotationZ;

            dataItem.RotateX = RotateX;
            dataItem.RotateY = RotateY;
            dataItem.RotateZ = RotateZ;

            dataItem.ArrowOffsetX = ArrowOffsetX;
            dataItem.ArrowOffsetY = ArrowOffsetY;
            dataItem.ArrowOffsetZ = ArrowOffsetZ;

            dataItem.ArrowRotationX = ArrowRotationX;
            dataItem.ArrowRotationY = ArrowRotationY;
            dataItem.ArrowRotationZ = ArrowRotationZ;

            //dataItem.ChildNodes = ChildNodes;

            #region File Service

            if (ChildNodes != null && ChildNodes.Any())
            {
                FileService fileService = new FileService();
                String xml = fileService.SaveToXml<ObservableCollection<VirtualWorld3DPluginDataItem>>(ChildNodes, XmlUtil.LoadSaveTypes);
                var childNodes = fileService.LoadFromXml<ObservableCollection<VirtualWorld3DPluginDataItem>>(xml, XmlUtil.LoadSaveTypes);
                RecursiveResetChildNodeIds(childNodes);
                dataItem.ChildNodes = childNodes;
                fileService = null;
            }

            #endregion

            //RecursiveResetChildNodeIds(dataItem.ChildNodes);

            DuplicateShape(dataItem);
            if (dataItem.Shape is SkewBoxMeshGenerator) (dataItem.Shape as SkewBoxMeshGenerator).RebuildMesh();

            return dataItem;
        }

        private void RecursiveResetChildNodeIds(ObservableCollection<VirtualWorld3DPluginDataItem> childNodes)
        {
            foreach (var node in childNodes)
            {
                node.NodeId = Guid.NewGuid();
                node.Id = Guid.NewGuid();

                if (node.ChildNodes.Any())
                {
                    RecursiveResetChildNodeIds(node.ChildNodes);
                }
            }
        }

        #endregion

    }
}