private static string SerializeSequenceType(this SequenceType sequence, IScopeProvider scope, string objectReference, 
            string valueReference, bool isRequired, Dictionary<Constraint, string> constraints, 
            string modelReference = "client._models", bool serializeInnerTypes = false)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }

            var builder = new IndentedStringBuilder("  ");
            var escapedObjectReference = objectReference.EscapeSingleQuotes();

            var indexVar = scope.GetVariableName("i");
            var innerConstraints = new Dictionary<Constraint, string>();
            var innerSerialization = sequence.ElementType.SerializeType(scope, objectReference + "[" + indexVar + "]", valueReference + "[" + indexVar + "]", false,
                innerConstraints, modelReference, true);
            if (!string.IsNullOrEmpty(innerSerialization))
            {
                if (isRequired)
                {
                    builder.AppendLine("if (!util.isArray({0})) {{", objectReference)
                             .Indent()
                             .AppendLine("throw new Error('{0} cannot be null or undefined and it must be of type {1}.');",
                             escapedObjectReference, sequence.Name.ToLower(CultureInfo.InvariantCulture))
                           .Outdent()
                           .AppendLine("}");
                    builder = sequence.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    builder.AppendLine("{0} = [];", valueReference)
                           .AppendLine("for (var {1} = 0; {1} < {0}.length; {1}++) {{", objectReference, indexVar)
                             .Indent()
                             .AppendLine(innerSerialization)
                           .Outdent()
                           .AppendLine("}");
                    return builder.ToString();
                }

                builder.AppendLine("if (util.isArray({0})) {{", objectReference).Indent();
                builder = sequence.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                builder.AppendLine("{0} = [];", valueReference)
                       .AppendLine("for (var {1} = 0; {1} < {0}.length; {1}++) {{", objectReference, indexVar)
                         .Indent()
                         .AppendLine(innerSerialization)
                       .Outdent()
                       .AppendLine("}")
                     .Outdent()
                     .AppendLine("}");
                return builder.ToString();
            }

            return null;
        }
        private static string SerializeCompositeType(this CompositeType composite, IScopeProvider scope, string objectReference, 
            string valueReference, bool isRequired, Dictionary<Constraint, string> constraints, string modelReference = "client._models", bool serializeInnerTypes = false)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }

            var builder = new IndentedStringBuilder("  ");
            var escapedObjectReference = objectReference.EscapeSingleQuotes();

            builder.AppendLine("if ({0}) {{", objectReference).Indent();
            builder = composite.AppendConstraintValidations(objectReference, constraints, builder);
            if (!string.IsNullOrEmpty(composite.PolymorphicDiscriminator))
            {
                builder.AppendLine("if({0}['{1}'] !== null && {0}['{1}'] !== undefined && {2}.discriminators[{0}['{1}']]) {{",
                                    objectReference,
                                    composite.PolymorphicDiscriminator, modelReference)
                    .Indent();
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                builder.AppendLine("{0} = {1}.serialize();", valueReference, objectReference)
                    .Outdent()
                    .AppendLine("}} else {{", valueReference)
                    .Indent()
                        .AppendLine("throw new Error('No discriminator field \"{0}\" was found in parameter \"{1}\".');",
                                    composite.PolymorphicDiscriminator,
                                    escapedObjectReference)
                    .Outdent()
                    .AppendLine("}");
            }
            else
            {
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                builder.AppendLine("{0} = {1}.serialize();", valueReference, objectReference);
            }
            builder.Outdent().AppendLine("}");

            if (isRequired)
            {
                builder.Append(" else {")
                    .Indent()
                        .AppendLine("throw new Error('{0} cannot be null or undefined.');", escapedObjectReference)
                    .Outdent()
                    .AppendLine("}");
            }
            return builder.ToString();
        }
        private static string SerializePrimaryType(this PrimaryType primary, IScopeProvider scope, 
            string objectReference, string valueReference, bool isRequired, Dictionary<Constraint, string> constraints, bool serializeInnerTypes = false)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }

            var builder = new IndentedStringBuilder("  ");
            var requiredTypeErrorMessage = "throw new Error('{0} cannot be null or undefined and it must be of type {1}.');";
            var typeErrorMessage = "throw new Error('{0} must be of type {1}.');";
            var lowercaseTypeName = primary.Name.ToLower(CultureInfo.InvariantCulture);

            if (primary == PrimaryType.Boolean ||
                primary == PrimaryType.Double ||
                primary == PrimaryType.Decimal ||
                primary == PrimaryType.Int ||
                primary == PrimaryType.Long ||
                primary == PrimaryType.Object)
            {
                if (isRequired)
                {
                    builder.AppendLine("if ({0} === null || {0} === undefined || typeof {0} !== '{1}') {{", 
                        objectReference, lowercaseTypeName);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = {1};", valueReference, objectReference).ToString();
                }
                builder.AppendLine("if ({0} !== null && {0} !== undefined) {{", objectReference)
                         .Indent()
                         .AppendLine("if (typeof {0} !== '{1}') {{", objectReference, lowercaseTypeName);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = {1};", valueReference, objectReference)
                            .Outdent()
                            .AppendLine("}").ToString();
            }
            else if (primary == PrimaryType.Stream)
            {
                if (isRequired)
                {
                    builder.AppendLine("if ({0} === null || {0} === undefined) {{", valueReference, lowercaseTypeName);
                    return ConstructValidationCheck(builder, requiredTypeErrorMessage, valueReference, primary.Name).ToString();
                }

                builder.AppendLine("if ({0} !== null && {0} !== undefined && typeof {0}.valueOf() !== '{1}') {{", valueReference, lowercaseTypeName);
                return ConstructValidationCheck(builder, typeErrorMessage, valueReference, primary.Name).ToString();
            }
            else if (primary == PrimaryType.String)
            {
                if (isRequired)
                {
                    //empty string can be a valid value hence we cannot implement the simple check if (!{0})
                    builder.AppendLine("if ({0} === null || {0} === undefined || typeof {0}.valueOf() !== '{1}') {{",
                        objectReference, lowercaseTypeName);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = {1};", valueReference, objectReference).ToString();
                }
                builder.AppendLine("if ({0} !== null && {0} !== undefined) {{", objectReference)
                         .Indent()
                         .AppendLine("if (typeof {0}.valueOf() !== '{1}') {{", objectReference, lowercaseTypeName);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = {1};", valueReference, objectReference)
                            .Outdent()
                            .AppendLine("}").ToString();
            }
            else if (primary == PrimaryType.ByteArray)
            {
                if (isRequired)
                {
                    builder.AppendLine("if (!Buffer.isBuffer({0})) {{", objectReference);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = {1}.toString('base64');", valueReference, objectReference).ToString();
                }
                builder.AppendLine("if ({0}) {{", objectReference)
                         .Indent()
                         .AppendLine("if (!Buffer.isBuffer({0})) {{", objectReference);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = {1}.toString('base64');", valueReference, objectReference)
                            .Outdent()
                            .AppendLine("}").ToString();
            }
            else if (primary == PrimaryType.Date)
            {
                if (isRequired)
                {
                    builder.AppendLine("if(!{0} || !({0} instanceof Date || (typeof {0}.valueOf() === 'string' && !isNaN(Date.parse({0}))))) {{", 
                        objectReference);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = ({1} instanceof Date) ? {1}.toISOString().substring(0,10) : {1};", 
                        valueReference, objectReference).ToString();
                }

                builder.AppendLine("if ({0}) {{", objectReference)
                         .Indent()
                         .AppendLine("if (!({0} instanceof Date || typeof {0}.valueOf() === 'string' && !isNaN(Date.parse({0})))) {{", 
                         objectReference);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = ({1} instanceof Date) ? {1}.toISOString().substring(0,10) : {1};", valueReference, objectReference)
                                .Outdent()
                                .AppendLine("}").ToString();
            }
            else if (primary == PrimaryType.DateTime)
            {
                if (isRequired)
                {
                    builder.AppendLine("if(!{0} || !({0} instanceof Date || (typeof {0}.valueOf() === 'string' && !isNaN(Date.parse({0}))))) {{",
                        objectReference);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = ({1} instanceof Date) ? {1}.toISOString() : {1};",
                        valueReference, objectReference).ToString();
                }

                builder.AppendLine("if ({0}) {{", objectReference)
                         .Indent()
                         .AppendLine("if (!({0} instanceof Date || typeof {0}.valueOf() === 'string' && !isNaN(Date.parse({0})))) {{",
                         objectReference);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = ({1} instanceof Date) ? {1}.toISOString() : {1};", valueReference, objectReference)
                                .Outdent()
                                .AppendLine("}").ToString();
            }
            else if (primary == PrimaryType.DateTimeRfc1123)
            {
                if (isRequired)
                {
                    builder.AppendLine("if(!{0} || !({0} instanceof Date || (typeof {0}.valueOf() === 'string' && !isNaN(Date.parse({0}))))) {{",
                        objectReference);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = ({1} instanceof Date) ? {1}.toUTCString() : {1};",
                        valueReference, objectReference).ToString();
                }

                builder.AppendLine("if ({0}) {{", objectReference)
                         .Indent()
                         .AppendLine("if (!({0} instanceof Date || typeof {0}.valueOf() === 'string' && !isNaN(Date.parse({0})))) {{",
                         objectReference);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = ({1} instanceof Date) ? {1}.toUTCString() : {1};", valueReference, objectReference)
                                .Outdent()
                                .AppendLine("}").ToString();
            }
            else if (primary == PrimaryType.TimeSpan)
            {
                if (isRequired)
                {
                    builder.AppendLine("if(!{0} || !moment.isDuration({0})) {{", objectReference);
                    builder = ConstructValidationCheck(builder, requiredTypeErrorMessage, objectReference, primary.Name);
                    builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    return builder.AppendLine("{0} = {1}.toISOString();", valueReference, objectReference).ToString();
                }

                builder.AppendLine("if ({0}) {{", objectReference)
                         .Indent()
                         .AppendLine("if (!moment.isDuration({0})) {{",
                         objectReference);
                builder = ConstructValidationCheck(builder, typeErrorMessage, objectReference, primary.Name);
                builder = primary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                return builder.AppendLine("{0} = {1}.toISOString();", valueReference, objectReference)
                                .Outdent()
                                .AppendLine("}").ToString();
            }
            else
            {
                throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture,
                    "'{0}' not implemented", valueReference));
            }
        }
        private static string SerializeEnumType(this EnumType enumType, IScopeProvider scope, 
            string objectReference, string valueReference, bool isRequired, Dictionary<Constraint, string> constraints, bool serializeInnerTypes = false)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }

            var builder = new IndentedStringBuilder("  ");
            var allowedValues = scope.GetVariableName("allowedValues");
            string tempReference = objectReference;
            builder.AppendLine("if ({0} !== null && {0} !== undefined) {{", objectReference).Indent();
            builder = enumType.AppendConstraintValidations(objectReference, constraints, builder);
            builder.AppendLine("var {0} = {1};", allowedValues, enumType.GetEnumValuesArray());
            if (objectReference.IndexOfAny(new char[] { '.', '[', ']'}) >= 0)
            {
                tempReference = tempReference.NormalizeValueReference();
                builder.AppendLine("var {0} = {1};", tempReference, objectReference);
            }
            builder.AppendLine("if (!{0}.some( function(item) {{ return item === {1}; }})) {{", allowedValues, tempReference)
                        .Indent()
                        .AppendLine("throw new Error({0} + ' is not a valid value. The valid values are: ' + {1});", objectReference, allowedValues)
                    .Outdent()
                    .AppendLine("}");
            if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
            builder.AppendLine("{0} = {1};", valueReference, objectReference);
            if (isRequired)
            {
                var escapedObjectReference = objectReference.EscapeSingleQuotes();
                builder.Outdent().AppendLine("} else {")
                    .Indent()
                        .AppendLine("throw new Error('{0} cannot be null or undefined.');", escapedObjectReference)
                    .Outdent()
                    .AppendLine("}");
            }
            else
            {
                builder.Outdent().AppendLine("}");
            }
            return builder.ToString();
        }
        private static string SerializeDictionaryType(this DictionaryType dictionary, IScopeProvider scope, string objectReference, string valueReference, 
            bool isRequired, Dictionary<Constraint, string> constraints, string modelReference = "client._models", bool serializeInnerTypes = false)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }

            var builder = new IndentedStringBuilder("  ");
            var escapedObjectReference = objectReference.EscapeSingleQuotes();
            var valueVar = scope.GetVariableName("valueElement");
            var innerConstraints = new Dictionary<Constraint, string>();
            var innerSerialization = dictionary.ValueType.SerializeType(scope, objectReference + "[" + valueVar + "]", valueReference + "[" + valueVar + "]", false,
                innerConstraints, modelReference, true);
            if (!string.IsNullOrEmpty(innerSerialization))
            {
                if (isRequired)
                {
                    builder.AppendLine("if ({0} === null || {0} === undefined || typeof {0} !== 'object') {{", objectReference)
                             .Indent()
                             .AppendLine("throw new Error('{0} cannot be null or undefined and it must be of type {1}.');",
                             escapedObjectReference, dictionary.Name.ToLower(CultureInfo.InvariantCulture))
                           .Outdent()
                           .AppendLine("}");
                    builder = dictionary.AppendConstraintValidations(objectReference, constraints, builder);
                    if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                    builder.AppendLine("{0} = {{}};", valueReference)
                      .AppendLine("for(var {0} in {1}) {{", valueVar, objectReference)
                        .Indent()
                          .AppendLine(innerSerialization)
                        .Outdent()
                      .AppendLine("}");
                    return builder.ToString();
                }

                builder.AppendLine("if ({0} && typeof {0} === 'object') {{", objectReference).Indent();
                builder = dictionary.AppendConstraintValidations(objectReference, constraints, builder);
                if (!serializeInnerTypes) builder = ConstructBasePropertyCheck(builder, valueReference);
                builder.AppendLine("{0} = {{}};", valueReference)
                       .AppendLine("for(var {0} in {1}) {{", valueVar, objectReference)
                         .Indent()
                         .AppendLine(innerSerialization)
                         .AppendLine("else {")
                           .Indent()
                           .AppendLine("{0} = {1};", valueReference + "[" + valueVar + "]", objectReference + "[" + valueVar + "]")
                         .Outdent()
                         .AppendLine("}")
                       .Outdent()
                       .AppendLine("}")
                     .Outdent()
                     .AppendLine("}");
                return builder.ToString();
            }

            return null;
        }