// Copyright 2016, University of Colorado Boulder

/**
 * Augments PHET_CORE/inherit by adding typeName, methods, supertype and convenience methods for PhET-iO.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var phetioNamespace = require( 'PHET_IO/phetioNamespace' );

  // constants
  var toImplementation = function( method ) {return method.implementation;};

  var setAllEvents = function( type ) {
    type.events = type.events || [];
    if ( type.typeName === 'TObject' ) {
      return type.events;
    }
    return type.events.concat( setAllEvents( type.supertype ) );
  };

  /**
   * @param {function} supertype Constructor for the supertype.
   * @param {string} typeName - the name for the type, used for logic (such as TVoid not needing a return, etc)
   * @param {function} subtype Constructor for the subtype. Generally should contain supertype.call( this, ... )
   * @param {Object} [methods] object containing properties that will be set on the prototype.
   * @param {Object} [staticProperties] object containing properties that will be set on the constructor function itself
   */
  var phetioInherit = function( supertype, typeName, subtype, methods, staticProperties ) {
    assert && assert( typeof typeName === 'string', 'typename must be 2nd arg' );
    assert && assert( typeof supertype === 'function' );

    // Copy implementations to the prototype for ease of use, see #185
    var prototypeMethods = _.mapValues( methods, toImplementation );

    inherit( supertype, subtype, prototypeMethods, staticProperties );

    subtype.typeName = typeName;
    subtype.methods = methods;
    subtype.supertype = supertype;

    /**
     * Look through the inheritance hierarchy to find the deepest (subtypiest) method declaration
     */
    subtype.getMethodDeclaration = function( methodName ) {
      if ( this.methods[ methodName ] ) {
        return this.methods[ methodName ];
      }
      else if ( typeName === 'TObject' ) {
        return null;
      }
      else {
        return supertype.getMethodDeclaration( methodName );
      }
    };

    // Combine the subtype's with events from all parents into a single array, see https://github.com/phetsims/phet-io/issues/1069
    subtype.allEvents = setAllEvents( subtype );

    subtype.allMethods = _.extend( {}, supertype.allMethods, methods );

    return subtype; // pass back the subtype so it can be returned immediately as a module export
  };

  phetioNamespace.register( 'phetioInherit', phetioInherit );

  return phetioInherit;
} );
@@ -535,229 +535,8 @@
 %7D;%0A%0A
-  var setAllEvents = function( type ) %7B%0A    type.events = type.events %7C%7C %5B%5D;%0A    if ( type.typeName === 'TObject' ) %7B%0A      return type.events;%0A    %7D%0A    return type.events.concat( setAllEvents( type.supertype ) );%0A  %7D;%0A%0A
   /*
@@ -2153,16 +2153,69 @@
 es/1069%0A
+    supertype.allEvents = supertype.allEvents %7C%7C %5B%5D;%0A
     subt
@@ -2235,19 +2235,26 @@
  = s
-etA
+upertype.a
 llEvents
 ( su
@@ -2249,16 +2249,23 @@
 llEvents
+.concat
 ( subtyp
@@ -2265,21 +2265,33 @@
  subtype
+.events %7C%7C %5B%5D
  );%0A
-%0A
     subt

simplify allEvents gathering, https://github.com/phetsims/phet-io/issues/1069