public string WriteModelToClass(
            GraphQLObjectModel model,
            string typesNamespace)
        {
            var sb = new StringBuilder();

            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using Newtonsoft.Json;");
            sb.AppendLine();
            sb.AppendFormat("namespace {0}", typesNamespace).AppendLine();
            sb.AppendLine("{");

            WriteEnumTypes(model.Enums, sb);
            WriteInterfaceTypes(model.Interfaces, model.Enums, sb);
            WriteObjectTypes(model.Objects, model.Enums, sb);
            WriteObjectTypes(model.InputObjects, model.Enums, sb);

            sb.AppendLine("}");
            return(sb.ToString());
        }
        public GraphQLObjectModel CoalesceToModel(
            List <GraphQLType> types)
        {
            var model = new GraphQLObjectModel();

            var interfaceNames = (from x in types
                                  from y in x.Interfaces
                                  orderby y
                                  select y).Distinct().ToList();

            var intrinsicTypeNames = (from x in types
                                      where x.Fields.Count == 0 &&
                                      x.InputFields.Count == 0 &&
                                      x.EnumValues.Count == 0 &&
                                      x.PossibleTypes.Count == 0
                                      orderby x.Name
                                      select x.Name).ToList();

            var inputTypes = (from x in types
                              where x.InputFields.Count > 0
                              orderby x.Name
                              select x).ToList();

            var inputTypesWithFields = (from x in inputTypes
                                        where x.Fields.Count > 0
                                        select x).ToList();

            if (inputTypesWithFields.Count > 0)
            {
                throw new Exception("Unexpected input type with data fields");
            }

            // Update Interface names to start with "I".
            var typesContainingInterfaces = (from x in types
                                             where x.Interfaces.Count > 0
                                             select x).ToList();

            foreach (var type in typesContainingInterfaces)
            {
                type.Interfaces = (from x in type.Interfaces
                                   let y = "I" + x
                                           select y).ToList();
            }

            // Update field names.
            foreach (var field in (from x in types
                                   from y in x.Fields
                                   where interfaceNames.Contains(y.TypeName) ||
                                   interfaceNames.Contains(y.OfTypeName)
                                   select y).ToList())
            {
                if (interfaceNames.Contains(field.TypeName))
                {
                    field.TypeName = "I" + field.TypeName;
                }

                if (interfaceNames.Contains(field.OfTypeName))
                {
                    field.OfTypeName = "I" + field.OfTypeName;
                }
            }

            // Update field names.
            foreach (var field in (from x in types
                                   from y in x.InputFields
                                   where interfaceNames.Contains(y.TypeName) ||
                                   interfaceNames.Contains(y.OfTypeName)
                                   select y).ToList())
            {
                if (interfaceNames.Contains(field.TypeName))
                {
                    field.TypeName = "I" + field.TypeName;
                }

                if (interfaceNames.Contains(field.OfTypeName))
                {
                    field.OfTypeName = "I" + field.OfTypeName;
                }
            }

            foreach (var type in types)
            {
                if (!type.Name.StartsWith("__"))
                {
                    if (type.EnumValues.Count > 0)
                    {
                        model.Enums.Add(type);
                    }
                    else if (interfaceNames.Contains(type.Name))
                    {
                        type.Name = "I" + type.Name;
                        model.Interfaces.Add(type);
                    }
                    else if (type.InputFields.Count > 0)
                    {
                        model.InputObjects.Add(type);
                    }
                    else if (!intrinsicTypeNames.Contains(type.Name))
                    {
                        model.Objects.Add(type);
                    }
                }
            }

            return(model);
        }