// Copyright 2018-2019, University of Colorado Boulder

/**
 * IO type for phet-core Enumeration that supports serializing and deserializing values.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( require => {
  'use strict';

  // modules
  const Enumeration = require( 'PHET_CORE/Enumeration' );
  const phetCore = require( 'PHET_CORE/phetCore' );
  const ObjectIO = require( 'TANDEM/types/ObjectIO' );

  /**
   * @param {Enumeration} enumeration
   * @module EnumerationIO
   * @constructor
   */
  function EnumerationIO( enumeration ) {
    assert && assert( enumeration, 'enumeration must be supplied' );
    assert && assert( enumeration instanceof Enumeration, 'enumeration must be an Enumeration' );

    class EnumerationIOImpl extends ObjectIO {
      constructor( a, b ) {
        assert && assert( false, 'This constructor is not called, because enumeration values, like primitives, are never wrapped.' );
        super( a, b );
      }

      /**
       * Encodes an Enumeration value to a string.
       * @param {Object} value from an Enumeration instance
       * @returns {Object} - a state object
       */
      static toStateObject( value ) {
        return toStateObjectImpl( value );
      }

      /**
       * Decodes a string into an Enumeration value.
       * @param {string} stateObject
       * @returns {Object}
       */
      static fromStateObject( stateObject ) {
        assert && assert( typeof stateObject === 'string', 'unsupported EnumerationIO value type, expected string' );
        assert && assert( enumeration.KEYS.indexOf( stateObject ) >= 0, `Unrecognized value: ${stateObject}` );
        return enumeration[ stateObject ];
      }

      /**
       * @override
       * @param {function(new:ObjectIO)} OtherEnumerationIO
       */
      static equals( OtherEnumerationIO ) {
        if ( this.typeName !== OtherEnumerationIO.typeName ) {
          return false;
        }
        if ( this.documentation !== OtherEnumerationIO.documentation ) {
          return false;
        }
        if ( this.enumeration !== OtherEnumerationIO.enumeration ) {
          return false;
        }
        return this.supertype.equals( OtherEnumerationIO.supertype ) &&
               OtherEnumerationIO.supertype.equals( this.supertype );
      }
    }

    const toStateObjectImpl = v => v.name;
    const valueNames = enumeration.VALUES.map( toStateObjectImpl );

    // Enumeration supports additional documentation, so the values can be described.
    const additionalDocs = enumeration.phetioDocumentation ? ` ${enumeration.phetioDocumentation}` : '';

    EnumerationIOImpl.validator = ObjectIO.validator; // TODO: is this redundant?
    EnumerationIOImpl.documentation = `Possible values: ${valueNames}.${additionalDocs}`;
    EnumerationIOImpl.typeName = `EnumerationIO.(${valueNames.join( '|' )})`;
    ObjectIO.validateSubtype( EnumerationIOImpl );

    return EnumerationIOImpl;
  }

  phetCore.register( 'EnumerationIO', EnumerationIO );

  return EnumerationIO;
} );
@@ -1697,608 +1697,8 @@
  %7D%0A%0A
-      /**%0A       * @override%0A       * @param %7Bfunction(new:ObjectIO)%7D OtherEnumerationIO%0A       */%0A      static equals( OtherEnumerationIO ) %7B%0A        if ( this.typeName !== OtherEnumerationIO.typeName ) %7B%0A          return false;%0A        %7D%0A        if ( this.documentation !== OtherEnumerationIO.documentation ) %7B%0A          return false;%0A        %7D%0A        if ( this.enumeration !== OtherEnumerationIO.enumeration ) %7B%0A          return false;%0A        %7D%0A        return this.supertype.equals( OtherEnumerationIO.supertype ) &&%0A               OtherEnumerationIO.supertype.equals( this.supertype );%0A      %7D%0A
     

remove IO type equals functions, https://github.com/phetsims/phet-io/issues/1371 https://github.com/phetsims/phet-io/issues/1549