module GraphQL::Client::Schema

def self.class_for(schema, type, cache)

def self.class_for(schema, type, cache)
  return cache[type] if cache[type]
  case type.kind.name
  when "INPUT_OBJECT"
    nil
  when "SCALAR"
    cache[type] = ScalarType.new(type)
  when "ENUM"
    cache[type] = EnumType.new(type)
  when "LIST"
    cache[type] = class_for(schema, type.of_type, cache).to_list_type
  when "NON_NULL"
    cache[type] = class_for(schema, type.of_type, cache).to_non_null_type
  when "UNION"
    klass = cache[type] = UnionType.new(type)
    type.possible_types.each do |possible_type|
      possible_klass = class_for(schema, possible_type, cache)
      possible_klass.send :include, klass
    end
    klass
  when "INTERFACE"
    cache[type] = InterfaceType.new(type)
  when "OBJECT"
    klass = cache[type] = ObjectType.new(type)
    type.interfaces.each do |interface|
      klass.send :include, class_for(schema, interface, cache)
    end
    # Legacy objects have `.all_fields`
    all_fields = type.respond_to?(:all_fields) ? type.all_fields : type.fields.values
    all_fields.each do |field|
      klass.fields[field.name.to_sym] = class_for(schema, field.type, cache)
    end
    klass
  else
    raise TypeError, "unexpected #{type.class} (#{type.inspect})"
  end
end

def self.generate(schema, raise_on_unknown_enum_value: true)

def self.generate(schema, raise_on_unknown_enum_value: true)
  mod = Module.new
  mod.extend ClassMethods
  mod.define_singleton_method(:raise_on_unknown_enum_value) { raise_on_unknown_enum_value }
  cache = {}
  schema.types.each do |name, type|
    next if name.start_with?("__")
    if klass = class_for(schema, type, cache)
      klass.schema_module = mod
      mod.set_class(name, klass)
    end
  end
  mod
end