// @flow
import { Composite, Pointer } from '@mytosis/types';

type GraphEntryPoints = {
  [title: string]: Composite,
};

const getFirstVersion = (composite: Composite) => {
  let ctx = composite;

  while (ctx.lastVersion) {
    ctx = ctx.lastVersion;
  }

  return ctx;
};

const everyVersionDo = (composite: Composite, fn: Composite => *) => {
  let ctx = getFirstVersion(composite);
  while (ctx) {
    fn(ctx);
    ctx = ctx.nextVersion;
  }
};

/** Validates and indexes a collection of types. */
export default class Schema {
  _types: Map<string, Composite> = new Map();

  /**
   * @param  {Object} types - A map of root-level types.
   */
  constructor(types: GraphEntryPoints) {
    const searchForTypes = (composite: Composite) => {
      everyVersionDo(composite, version => {
        const id = String(version);
        this._types.set(id, version);
      });

      // Follow type pointers.
      if (composite.defaultType instanceof Pointer) {
        searchForTypes(composite.defaultType.to);
      }

      Object.keys(composite.definition).forEach(key => {
        const type = composite.definition[key];

        if (type instanceof Pointer) {
          searchForTypes(type.to);
        }
      });
    };

    Object.keys(types).forEach(key => {
      const composite = types[key];
      searchForTypes(composite);
    });
  }

  /**
   * Looks for a type in the schema.
   * @param  {String} id - Any type ID, like Product@version.
   * @return {?Composite} - An object type.
   */
  findType(id: string): ?Composite {
    return this._types.get(id) || null;
  }
}

@@ -120,337 +120,8 @@
 %7D;%0A%0A
-const getFirstVersion = (composite: Composite) =%3E %7B%0A  let ctx = composite;%0A%0A  while (ctx.lastVersion) %7B%0A    ctx = ctx.lastVersion;%0A  %7D%0A%0A  return ctx;%0A%7D;%0A%0Aconst everyVersionDo = (composite: Composite, fn: Composite =%3E *) =%3E %7B%0A  let ctx = getFirstVersion(composite);%0A  while (ctx) %7B%0A    fn(ctx);%0A    ctx = ctx.nextVersion;%0A  %7D%0A%7D;%0A%0A
 /** 
@@ -420,44 +420,68 @@
     
-everyVersionDo(composite, version =%3E
+for (const type of Composite.toMigrationIterable(composite))
  %7B%0A 
@@ -505,23 +505,20 @@
  String(
-version
+type
 );%0A     
@@ -540,23 +540,20 @@
 set(id, 
-version
+type
 );%0A     
@@ -554,18 +554,16 @@
 %0A      %7D
-);
 %0A%0A      

Replace iterator utils with composite API