/// <summary>
        ///     Main executor function.
        /// </summary>
        /// <returns>A CodeCompileUnit.</returns>
        public CodeCompileUnit Execute()
        {
            var codeCompileUnit = new CodeCompileUnit();

            // Set namespace
            var nsWrap = new NamespaceWrapper(new CodeNamespace(_codeNamespace));

            // Set class
            var codeClass = new CodeTypeDeclaration(_schemaDocument.Title) {Attributes = MemberAttributes.Public};
            var clWrap = new ClassWrapper(codeClass);

            // Add imports for interfaces and dependencies
            nsWrap.AddImportsFromWrapper(_schemaWrapper);

            // Add comments and attributes for class
            if (!String.IsNullOrEmpty(_schemaDocument.Description))
            {
                clWrap.AddComment(_schemaDocument.Description);
            }

            // Add extended class
            if (_schemaDocument.Extends != null && _schemaDocument.Extends.Count > 0)
            {
                clWrap.AddInterface(JsonSchemaUtils.GetType(_schemaDocument.Extends[0], _codeNamespace).Name);
            }

            // Add interfaces
            foreach (Type t in _schemaWrapper.Interfaces)
            {
                clWrap.AddInterface(t.Name);
            }

            // Add properties with getters/setters
            if (_schemaDocument.Properties != null)
            {
                foreach (var i in _schemaDocument.Properties)
                {
                    JsonSchema schema = i.Value;

                    // Sanitize inputs
                    if (!String.IsNullOrEmpty(schema.Description))
                    {
                        schema.Description = Regex.Unescape(schema.Description);
                    }

                    // If it is an enum
                    var propertyName = i.Key.Capitalize();
                    if (schema.Enum != null)
                    {
                        var enumField = new CodeTypeDeclaration(propertyName);
                        var enumWrap = new EnumWrapper(enumField);

                        // Add comment if not null
                        if (!String.IsNullOrEmpty(schema.Description))
                        {
                            enumField.Comments.Add(new CodeCommentStatement(schema.Description));
                        }

                        foreach (JToken j in schema.Enum)
                        {
                            enumWrap.AddMember(j.ToString().SanitizeIdentifier());
                        }

                        // Add to namespace
                        nsWrap.AddClass(enumWrap.Property);
                    }
                    else
                    {
                        // WARNING: This assumes the namespace of the property is the same as the parent.
                        // This should not be a problem since imports are handled for all dependencies at the beginning.
                        Type type = JsonSchemaUtils.GetType(schema, _codeNamespace);
                        bool isCustomType = type.Namespace != null && type.Namespace.Equals(_codeNamespace);
                        string strType = String.Empty;

                        // Add imports
                        nsWrap.AddImport(type.Namespace);
                        nsWrap.AddImportsFromSchema(schema);

                        // Get the property type
                        if (isCustomType)
                        {
                            strType = JsonSchemaUtils.IsArray(schema) ? string.Format("{0}<{1}>", JsonSchemaUtils.GetArrayType(schema), type.Name) : type.Name;
                        }
                        else if (JsonSchemaUtils.IsArray(schema))
                        {
                            strType = string.Format("{0}<{1}>", JsonSchemaUtils.GetArrayType(schema),
                                new CSharpCodeProvider().GetTypeOutput(new CodeTypeReference(type)));
                        }

                        //var field = new CodeMemberField
                        //{
                        //    Attributes = MemberAttributes.Private,
                        //    Name = "_" + i.Key,
                        //    Type =
                        //        TypeUtils.IsPrimitive(type) && !JsonSchemaUtils.IsArray(schema)
                        //            ? new CodeTypeReference(type)
                        //            : new CodeTypeReference(strType)
                        //};


                        //clWrap.Property.Members.Add(field);

                        var property = CreateProperty(propertyName, TypeUtils.IsPrimitive(type) && !JsonSchemaUtils.IsArray(schema)
                                    ? new CodeTypeReference(type)
                                    : new CodeTypeReference(strType));

                        var prWrap = new PropertyWrapper(property);

                        // Add comments and attributes
                        prWrap.Populate(schema, _attributeType);

                        // Add default, if any
                        if (schema.Default != null)
                        {
                            clWrap.AddDefault(propertyName, property.Type, schema.Default.ToString());
                        }

                        clWrap.Property.Members.Add(property);
                    }
                }
            }

            // Add class to namespace
            nsWrap.AddClass(clWrap.Property);
            codeCompileUnit.Namespaces.Add(nsWrap.Namespace);

            return codeCompileUnit;
        }
        /// <summary>
        ///     Main executor function.
        /// </summary>
        /// <returns>A CodeCompileUnit.</returns>
        public CodeCompileUnit Execute()
        {
            var codeCompileUnit = new CodeCompileUnit();

            // Set namespace
            var nsWrap = new NamespaceWrapper(new CodeNamespace(_codeNamespace));

            // Set class
            var codeClass = new CodeTypeDeclaration(_schemaDocument.Title)
            {
                Attributes = MemberAttributes.Public
            };
            var clWrap = new ClassWrapper(codeClass);

            // Add imports for interfaces and dependencies
            nsWrap.AddImportsFromWrapper(_schemaWrapper);

            // Add comments and attributes for class
            if (!String.IsNullOrEmpty(_schemaDocument.Description))
            {
                clWrap.AddComment(_schemaDocument.Description);
            }

            // Add extended class
            if (_schemaDocument.Extends != null && _schemaDocument.Extends.Count > 0)
            {
                clWrap.AddInterface(JsonSchemaUtils.GetType(_schemaDocument.Extends[0], _codeNamespace).Name);
            }

            // Add interfaces
            foreach (Type t in _schemaWrapper.Interfaces)
            {
                clWrap.AddInterface(t.Name);
            }

            // Add properties with getters/setters
            if (_schemaDocument.Properties != null)
            {
                foreach (var i in _schemaDocument.Properties)
                {
                    JsonSchema schema = i.Value;

                    // Sanitize inputs
                    if (!String.IsNullOrEmpty(schema.Description))
                    {
                        schema.Description = Regex.Unescape(schema.Description);
                    }

                    // If it is an enum
                    var propertyName = i.Key.Capitalize();
                    if (schema.Enum != null)
                    {
                        var enumField = new CodeTypeDeclaration(propertyName);
                        var enumWrap  = new EnumWrapper(enumField);

                        // Add comment if not null
                        if (!String.IsNullOrEmpty(schema.Description))
                        {
                            enumField.Comments.Add(new CodeCommentStatement(schema.Description));
                        }

                        foreach (JToken j in schema.Enum)
                        {
                            enumWrap.AddMember(j.ToString().SanitizeIdentifier());
                        }

                        // Add to namespace
                        nsWrap.AddClass(enumWrap.Property);
                    }
                    else
                    {
                        // WARNING: This assumes the namespace of the property is the same as the parent.
                        // This should not be a problem since imports are handled for all dependencies at the beginning.
                        Type   type         = JsonSchemaUtils.GetType(schema, _codeNamespace);
                        bool   isCustomType = type.Namespace != null && type.Namespace.Equals(_codeNamespace);
                        string strType      = String.Empty;

                        // Add imports
                        nsWrap.AddImport(type.Namespace);
                        nsWrap.AddImportsFromSchema(schema);

                        // Get the property type
                        if (isCustomType)
                        {
                            strType = JsonSchemaUtils.IsArray(schema) ? string.Format("{0}<{1}>", JsonSchemaUtils.GetArrayType(schema), type.Name) : type.Name;
                        }
                        else if (JsonSchemaUtils.IsArray(schema))
                        {
                            strType = string.Format("{0}<{1}>", JsonSchemaUtils.GetArrayType(schema),
                                                    new CSharpCodeProvider().GetTypeOutput(new CodeTypeReference(type)));
                        }

                        //var field = new CodeMemberField
                        //{
                        //    Attributes = MemberAttributes.Private,
                        //    Name = "_" + i.Key,
                        //    Type =
                        //        TypeUtils.IsPrimitive(type) && !JsonSchemaUtils.IsArray(schema)
                        //            ? new CodeTypeReference(type)
                        //            : new CodeTypeReference(strType)
                        //};


                        //clWrap.Property.Members.Add(field);

                        var property = CreateProperty(propertyName, TypeUtils.IsPrimitive(type) && !JsonSchemaUtils.IsArray(schema)
                                    ? new CodeTypeReference(type)
                                    : new CodeTypeReference(strType));

                        var prWrap = new PropertyWrapper(property);

                        // Add comments and attributes
                        prWrap.Populate(schema, _attributeType);

                        // Add default, if any
                        if (schema.Default != null)
                        {
                            clWrap.AddDefault(propertyName, property.Type, schema.Default.ToString());
                        }

                        clWrap.Property.Members.Add(property);
                    }
                }
            }

            // Add class to namespace
            nsWrap.AddClass(clWrap.Property);
            codeCompileUnit.Namespaces.Add(nsWrap.Namespace);

            return(codeCompileUnit);
        }