/// <summary>
        /// Creates a root node view model
        /// </summary>
        private JMXStructure(string Name, Type ChildType = null) : base(Name, ChildType != null)
        {
            // Make sure the type is specified
            if (ChildType == null)
            {
                CommandAddChild    = new RelayCommand(() => { /* Do Nothing... */ });
                CommandRemoveChild = new RelayCommand(() => { /* Do Nothing... */ });
                return;
            }

            /// Commands setup
            CommandAddChild = new RelayCommand(() =>
            {
                /// Create and add a default instance to nodes queue
                string name = "[" + Childs.Count.ToString() + "]";
                // default value types
                if (ChildType == typeof(byte))
                {
                    Childs.Add(new JMXAttribute(name, default(byte)));
                }
                else if (ChildType == typeof(uint))
                {
                    Childs.Add(new JMXAttribute(name, default(uint)));
                }
                else
                {
                    // default classes types
                    var nodeClass = new JMXStructure(name);
                    if (ChildType == typeof(JMXVRES_0109.Material))
                    {
                        var material = new JMXVRES_0109.Material();
                        nodeClass.Childs.Add(new JMXAttribute("Index", material.Index));
                        nodeClass.Childs.Add(new JMXAttribute("Path", material.Path));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.Mesh))
                    {
                        var mesh = new JMXVRES_0109.Mesh();
                        nodeClass.Childs.Add(new JMXAttribute("Path", mesh.Path));
                        nodeClass.Childs.Add(new JMXAttribute("UnkUInt01", mesh.UnkUInt01));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.Animation))
                    {
                        var animation = new JMXVRES_0109.Animation();
                        nodeClass.Childs.Add(new JMXAttribute("Path", animation.Path));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.Skeleton))
                    {
                        var skeleton = new JMXVRES_0109.Skeleton();
                        nodeClass.Childs.Add(new JMXAttribute("Path", skeleton.Path));
                        nodeClass.Childs.Add(new JMXAttribute("ExtraBone", skeleton.ExtraBone));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.MeshGroup))
                    {
                        var meshGroup = new JMXVRES_0109.MeshGroup();
                        nodeClass.Childs.Add(new JMXAttribute("Name", meshGroup.Name));
                        nodeClass.Childs.Add(new JMXStructure("FileIndexes", typeof(uint)));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.AnimationGroup))
                    {
                        var animationGroup = new JMXVRES_0109.AnimationGroup();
                        nodeClass.Childs.Add(new JMXAttribute("Name", animationGroup.Name));
                        nodeClass.Childs.Add(new JMXStructure("Entries", typeof(JMXVRES_0109.AnimationGroup.Entry)));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.AnimationGroup.Entry))
                    {
                        var animationGroupEntry = new JMXVRES_0109.AnimationGroup.Entry();
                        nodeClass.Childs.Add(new JMXOption("Type", animationGroupEntry.Type, GetValues <object>(typeof(ResourceAnimationType))));
                        nodeClass.Childs.Add(new JMXAttribute("FileIndex", animationGroupEntry.FileIndex));
                        nodeClass.Childs.Add(new JMXStructure("Events", typeof(JMXVRES_0109.AnimationGroup.Entry.Event)));
                        nodeClass.Childs.Add(new JMXAttribute("WalkingLength", animationGroupEntry.WalkingLength));
                        nodeClass.Childs.Add(new JMXStructure("WalkPoints", typeof(JMXVRES_0109.AnimationGroup.Entry.Point)));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.AnimationGroup.Entry.Event))
                    {
                        var animationGroupEntryEvent = new JMXVRES_0109.AnimationGroup.Entry.Event();
                        nodeClass.Childs.Add(new JMXAttribute("KeyTime", animationGroupEntryEvent.KeyTime));
                        nodeClass.Childs.Add(new JMXAttribute("Type", animationGroupEntryEvent.Type));
                        nodeClass.Childs.Add(new JMXAttribute("UnkUInt01", animationGroupEntryEvent.UnkUInt01));
                        nodeClass.Childs.Add(new JMXAttribute("UnkUInt02", animationGroupEntryEvent.UnkUInt02));
                    }
                    else if (ChildType == typeof(JMXVRES_0109.AnimationGroup.Entry.Point))
                    {
                        var animationGroupEntryEventPoint = new JMXVRES_0109.AnimationGroup.Entry.Point();
                        nodeClass.Childs.Add(new JMXAttribute("X", animationGroupEntryEventPoint.X));
                        nodeClass.Childs.Add(new JMXAttribute("Y", animationGroupEntryEventPoint.Y));
                    }
                    else
                    {
                        // type not found
                        return;
                    }
                    Childs.Add(nodeClass);
                }
            });
            CommandRemoveChild = new RelayParameterizedCommand((object parameter) =>
            {
                // Make sure the item to remove is a correct value
                if (parameter is JMXProperty property)
                {
                    // Try to remove it
                    Childs.Remove(property);
                }
            });
        }
        /// <summary>
        /// Converts the structure into a JMXFile.
        /// This method only work with a root JMXStructure
        /// </summary>
        public IJMXFile ToJMXFile()
        {
            // Read format
            string header = (string)((JMXAttribute)Childs[0]).Value;

            if (header == JMXVRES_0109.FileHeader)
            {
                JMXVRES_0109 file = new JMXVRES_0109();
                file.Header = header;
                // Pointers will be calculated in the process
                // Flags
                file.FlagUInt01 = (uint)((JMXAttribute)Childs[9]).Value;
                file.FlagUInt02 = (uint)((JMXAttribute)Childs[10]).Value;
                file.FlagUInt03 = (uint)((JMXAttribute)Childs[11]).Value;
                file.FlagUInt04 = (uint)((JMXAttribute)Childs[12]).Value;
                file.FlagUInt05 = (uint)((JMXAttribute)Childs[13]).Value;
                // Details
                file.ResourceType = (ResourceType)((JMXOption)Childs[14]).Value;
                file.Name         = (string)((JMXAttribute)Childs[15]).Value;
                var nodeChilds = ((JMXStructure)Childs[16]).Childs;
                file.UnkByteArray01 = new byte[nodeChilds.Count];
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    file.UnkByteArray01[i] = (byte)((JMXAttribute)nodeChilds[i]).Value;
                }

                // Pointer.BoundingBox
                file.RootMesh      = (string)((JMXAttribute)Childs[17]).Value;
                nodeChilds         = ((JMXStructure)Childs[18]).Childs;
                file.BoundingBox01 = new float[nodeChilds.Count];
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    file.BoundingBox01[i] = (float)((JMXAttribute)nodeChilds[i]).Value;
                }
                nodeChilds         = ((JMXStructure)Childs[19]).Childs;
                file.BoundingBox02 = new float[nodeChilds.Count];
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    file.BoundingBox02[i] = (float)((JMXAttribute)nodeChilds[i]).Value;
                }
                nodeChilds             = ((JMXStructure)Childs[20]).Childs;
                file.ExtraBoundingData = new byte[nodeChilds.Count];
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    file.ExtraBoundingData[i] = (byte)((JMXAttribute)nodeChilds[i]).Value;
                }

                // Pointer.Material
                nodeChilds     = ((JMXStructure)Childs[21]).Childs;
                file.Materials = new List <JMXVRES_0109.Material>(nodeChilds.Count);
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    // Create
                    var material = new JMXVRES_0109.Material();
                    file.Materials.Add(material);
                    // Copy
                    var nodeClass = ((JMXStructure)nodeChilds[i]).Childs;
                    material.Index = (uint)((JMXAttribute)nodeClass[0]).Value;
                    material.Path  = (string)((JMXAttribute)nodeClass[1]).Value;
                }

                // Pointer.Mesh
                nodeChilds  = ((JMXStructure)Childs[22]).Childs;
                file.Meshes = new List <JMXVRES_0109.Mesh>(nodeChilds.Count);
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    // Create
                    var mesh = new JMXVRES_0109.Mesh();
                    file.Meshes.Add(mesh);
                    // Copy
                    var nodeClass = ((JMXStructure)nodeChilds[i]).Childs;
                    mesh.Path      = (string)((JMXAttribute)nodeClass[0]).Value;
                    mesh.UnkUInt01 = (uint)((JMXAttribute)nodeClass[1]).Value;
                }

                // Pointer.Animation
                file.UnkUInt01  = (uint)((JMXAttribute)Childs[23]).Value;
                file.UnkUInt02  = (uint)((JMXAttribute)Childs[24]).Value;
                nodeChilds      = ((JMXStructure)Childs[25]).Childs;
                file.Animations = new List <JMXVRES_0109.Animation>(nodeChilds.Count);
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    // Create
                    var animation = new JMXVRES_0109.Animation();
                    file.Animations.Add(animation);
                    // Copy
                    var nodeClass = ((JMXStructure)nodeChilds[i]).Childs;
                    animation.Path = (string)((JMXAttribute)nodeClass[0]).Value;
                }

                // Pointer.Skeleton
                nodeChilds     = ((JMXStructure)Childs[26]).Childs;
                file.Skeletons = new List <JMXVRES_0109.Skeleton>(nodeChilds.Count);
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    // Create
                    var skeleton = new JMXVRES_0109.Skeleton();
                    file.Skeletons.Add(skeleton);
                    // Copy
                    var nodeClass = ((JMXStructure)nodeChilds[i]).Childs;
                    skeleton.Path      = (string)((JMXAttribute)nodeClass[0]).Value;
                    skeleton.ExtraBone = (string)((JMXAttribute)nodeClass[1]).Value;
                }

                // Pointer.MeshGroup
                nodeChilds      = ((JMXStructure)Childs[27]).Childs;
                file.MeshGroups = new List <JMXVRES_0109.MeshGroup>(nodeChilds.Count);
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    // Create
                    var meshGroup = new JMXVRES_0109.MeshGroup();
                    file.MeshGroups.Add(meshGroup);
                    // Copy
                    var nodeClass = ((JMXStructure)nodeChilds[i]).Childs;
                    meshGroup.Name = (string)((JMXAttribute)nodeClass[0]).Value;
                    var _nodeChilds = ((JMXStructure)nodeClass[1]).Childs;
                    meshGroup.FileIndexes = new uint[_nodeChilds.Count];
                    for (int j = 0; j < _nodeChilds.Count; j++)
                    {
                        meshGroup.FileIndexes[j] = (uint)((JMXAttribute)_nodeChilds[j]).Value;
                    }
                }

                // Pointer.AnimationGroups
                nodeChilds           = ((JMXStructure)Childs[28]).Childs;
                file.AnimationGroups = new List <JMXVRES_0109.AnimationGroup>(nodeChilds.Count);
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    // Create
                    var animationGroup = new JMXVRES_0109.AnimationGroup();
                    file.AnimationGroups.Add(animationGroup);
                    // Copy
                    var nodeClass = ((JMXStructure)nodeChilds[i]).Childs;
                    animationGroup.Name = (string)((JMXAttribute)nodeClass[0]).Value;
                    var _nodeChilds = ((JMXStructure)nodeClass[1]).Childs;
                    animationGroup.Entries = new List <JMXVRES_0109.AnimationGroup.Entry>();;
                    for (int j = 0; j < _nodeChilds.Count; j++)
                    {
                        // Create
                        var entry = new JMXVRES_0109.AnimationGroup.Entry();
                        animationGroup.Entries.Add(entry);
                        // Copy
                        var _nodeClass = ((JMXStructure)_nodeChilds[j]).Childs;
                        entry.Type      = (ResourceAnimationType)((JMXOption)_nodeClass[0]).Value;
                        entry.FileIndex = (uint)((JMXAttribute)_nodeClass[1]).Value;
                        var __nodeChilds = ((JMXStructure)_nodeClass[2]).Childs;
                        entry.Events = new List <JMXVRES_0109.AnimationGroup.Entry.Event>();
                        for (int k = 0; k < __nodeChilds.Count; k++)
                        {
                            // Create
                            var _event = new JMXVRES_0109.AnimationGroup.Entry.Event();
                            entry.Events.Add(_event);
                            // Copy
                            var __nodeClass = ((JMXStructure)__nodeChilds[k]).Childs;
                            _event.KeyTime   = (uint)((JMXAttribute)__nodeClass[0]).Value;
                            _event.Type      = (uint)((JMXAttribute)__nodeClass[1]).Value;
                            _event.UnkUInt01 = (uint)((JMXAttribute)__nodeClass[2]).Value;
                            _event.UnkUInt02 = (uint)((JMXAttribute)__nodeClass[3]).Value;
                        }
                        entry.WalkingLength = (float)((JMXAttribute)_nodeClass[3]).Value;
                        __nodeChilds        = ((JMXStructure)_nodeClass[4]).Childs;
                        entry.WalkPoints    = new List <JMXVRES_0109.AnimationGroup.Entry.Point>();
                        for (int k = 0; k < __nodeChilds.Count; k++)
                        {
                            // Create
                            var point = new JMXVRES_0109.AnimationGroup.Entry.Point();
                            entry.WalkPoints.Add(point);
                            // Copy
                            var __nodeClass = ((JMXStructure)__nodeChilds[k]).Childs;
                            point.X = (float)((JMXAttribute)__nodeClass[0]).Value;
                            point.Y = (float)((JMXAttribute)__nodeClass[1]).Value;
                        }
                    }
                }

                // Pointer.SoundEffect
                nodeChilds = ((JMXStructure)Childs[29]).Childs;
                file.SoundEffectUndecodedBytes = new byte[nodeChilds.Count];
                for (int i = 0; i < nodeChilds.Count; i++)
                {
                    file.SoundEffectUndecodedBytes[i] = (byte)((JMXAttribute)nodeChilds[i]).Value;
                }

                // Return result
                return(file);
            }
            return(null);
        }