private void WriteTypeConstructor(ProtoType type)
        {
            WriteLine("initialize: function ($super, values) {");
            Indent();

            if (type.Members.Count > 0)
            {
                foreach (var member in type.Members)
                {
                    if (member.IsCollection)
                        WriteLine("this.{0} = [];", EncodeName(member.Name));
                    else
                        WriteLine("this.{0} = {1};", EncodeName(member.Name), Encode(member.DefaultValue));
                }

                WriteLine();
            }

            WriteLine("$super(values);");

            Unindent();
            WriteLine("},");
        }
        private void WriteType(ProtoType type)
        {
            if (type.MessageId.HasValue)
                WriteLine("{0} = Class.create(ProtoMessage, {{", TypeName(type.Type));
            else
                WriteLine("{0} = Class.create(ProtoType, {{", TypeName(type.Type));

            Indent();

            if (type.MessageId.HasValue)
                WriteMessageConstructor(type);
            else
                WriteTypeConstructor(type);

            WriteLine();

            WriteMessageSerialize(type);

            WriteLine();

            WriteMessageDeserializer(type);

            Unindent();
            WriteLine("});");

            if (type.MessageId.HasValue)
            {
                WriteLine();
                WriteLine("ProtoRegistry.registerType({0}, {1});", TypeName(type.Type), type.MessageId);
            }
        }
        private void WriteMessageDeserializer(ProtoType type)
        {
            WriteLine("deserialize: function (message) {");
            Indent();

            foreach (var member in type.Members)
            {
                WriteLine("if (message[{0}] !== undefined) {{", member.Tag);
                Indent();

                    WriteLine("this.{0}Provided = true;", EncodeName(member.Name));

                    if (GetProtoContractType(member.Type) == null || member.Type.IsEnum)
                    {
                        WriteLine("this.{0} = message[{1}];", EncodeName(member.Name), member.Tag);
                    }
                    else if (member.IsCollection)
                    {
                        WriteLine("this.{0} = [];", EncodeName(member.Name));

                        WriteLine("for (var i = 0; i < message[{0}].length; i++) {{", member.Tag);
                        Indent();

                        WriteLine("var value = message[{0}][i];", member.Tag);

                        WriteLine("if (value === null) {");
                        Indent();

                        WriteLine("this.{0}.push(null);", EncodeName(member.Name));

                        Unindent();
                        WriteLine("} else {");
                        Indent();

                        WriteLine("var item = new {0}();", TypeName(member.Type));
                        WriteLine("item.deserialize(value);");
                        WriteLine("this.{0}.push(item);", EncodeName(member.Name));

                        Unindent();
                        WriteLine("}");

                        Unindent();
                        WriteLine("}");
                    }
                    else
                    {
                        WriteLine("if (message[{0}] === null) {{", member.Tag);
                        Indent();

                        WriteLine("this.{0} = null;", EncodeName(member.Name));

                        Unindent();
                        WriteLine("} else {");
                        Indent();

                        WriteLine("var item = new {0}();", TypeName(member.Type));
                        WriteLine("item.deserialize(message[{0}]);", member.Tag);
                        WriteLine("this.{0} = item;", EncodeName(member.Name));

                        Unindent();
                        WriteLine("}");
                    }

                Unindent();
                WriteLine("}");
            }

            Unindent();
            WriteLine("}");
        }
        private void WriteMessageSerialize(ProtoType type)
        {
            WriteLine("serialize: function () {");
            Indent();

            WriteLine("var message = {};");
            WriteLine();

            if (type.Members.Count > 0)
            {
                foreach (var member in type.Members)
                {
                    if (member.IsCollection)
                    {
                        WriteLine("if (this.{0} !== null && this.{0}.length > 0) {{", EncodeName(member.Name));
                        Indent();

                        if (GetProtoContractType(member.Type) == null)
                        {
                            WriteLine("message[{0}] = this.{1};", member.Tag, EncodeName(member.Name));
                        }
                        else
                        {
                            WriteLine("var items = [];");
                            WriteLine("for (var i = 0; i < this.{0}.length; i++) {{", EncodeName(member.Name));
                            Indent();

                            if (member.Type.IsEnum)
                            {
                                WriteLine("items.push(this.{0}[i].serialize());", EncodeName(member.Name));
                            }
                            else
                            {
                                WriteLine("var item = this.{0}[i];", EncodeName(member.Name));

                                WriteLine("if (!(item instanceof {0})) {{", TypeName(member.Type));
                                Indent();
                                WriteLine("item = new {0}(item);", TypeName(member.Type));
                                Unindent();
                                WriteLine("}");

                                WriteLine("items.push(item.serialize());");
                            }

                            Unindent();
                            WriteLine("}");

                            WriteLine("message[{0}] = items;", member.Tag);
                        }

                        Unindent();
                        WriteLine("}");
                    }
                    else
                    {
                        WriteLine("if (this.{0} !== {1}) {{", EncodeName(member.Name), Encode(member.DefaultValue));

                        Indent();

                        if (GetProtoContractType(member.Type) == null || member.Type.IsEnum)
                        {
                            WriteLine("message[{0}] = this.{1};", member.Tag, EncodeName(member.Name));
                        }
                        else
                        {
                            WriteLine("var item = this.{0};", EncodeName(member.Name));
                            WriteLine("if (!(item instanceof {0})) {{", TypeName(member.Type));
                            Indent();
                            WriteLine("item = new {0}(item);", TypeName(member.Type));
                            Unindent();
                            WriteLine("}");

                            WriteLine("message[{0}] = item.serialize();", member.Tag);
                        }

                        Unindent();
                        WriteLine("}");
                    }
                }

                WriteLine();
            }

            WriteLine("return message;");

            Unindent();
            WriteLine("},");
        }
        private void WriteEnumType(ProtoType type)
        {
            WriteLine("{0} = {{", TypeName(type.Type));

            var values = Enum.GetValues(type.Type);

            for (int i = 0; i < values.Length; i++)
            {
                WriteLine("    {0}: {1}{2}", values.GetValue(i), (int)values.GetValue(i), i < values.Length - 1 ? "," : "");
            }

            WriteLine("};");
        }