// Copyright 2018-2020, University of Colorado Boulder

/**
 * "definition" type for generalized color paints (anything that can be given to a fill/stroke that represents just a
 * solid color). Does NOT include any type of gradient or pattern.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

import Property from '../../../axon/js/Property.js';
import IOType from '../../../tandem/js/types/IOType.js';
import NullableIO from '../../../tandem/js/types/NullableIO.js';
import OrIO from '../../../tandem/js/types/OrIO.js';
import ReferenceIO from '../../../tandem/js/types/ReferenceIO.js';
import StringIO from '../../../tandem/js/types/StringIO.js';
import scenery from '../scenery.js';
import Color from './Color.js';

const ColorDef = {
  /**
   * Returns whether the parameter is considered to be a ColorDef.
   * @public
   *
   * @param {*} color
   * @returns {boolean}
   */
  isColorDef( color ) {
    return color === null ||
           typeof color === 'string' ||
           color instanceof Color ||
           ( color instanceof Property && (
             color.value === null ||
             typeof color.value === 'string' ||
             color.value instanceof Color
           ) );
  }
};

// @public - phet-io IOType for serialization and documentation
ColorDef.ColorDefIO = new IOType( 'ColorDefIO', {
  isValidValue: ColorDef.isColorDef,
  supertype: NullableIO( OrIO( [ StringIO, Color.ColorIO, ReferenceIO( Property.PropertyIO( NullableIO( OrIO( [ StringIO, Color.ColorIO ] ) ) ) ) ] ) )
} );

scenery.register( 'ColorDef', ColorDef );

export default ColorDef;
@@ -747,16 +747,1279 @@
 Def = %7B%0A
+%0A  /**%0A   * Link a listener to the given colorDef instance.  For a non-Property, this just calls back the listener with the value.%0A   * For a Property, it is linked and called back with the value.%0A   * @param %7BColorDef%7D color%0A   * @param %7Bfunction%7D listener%0A   * @public%0A   * @static%0A   */%0A  link( color, listener ) %7B%0A    assert && assert( ColorDef.isColorDef( color ), 'must be a colorDef' );%0A    if ( color instanceof Property ) %7B%0A      color.link( listener );%0A    %7D%0A    else %7B%0A      listener( color );%0A    %7D%0A  %7D,%0A%0A  /**%0A   * Unlink a listener from a colorDef instance.  For a non-Property, this is a no-op. For a Property, it is linked and%0A   * called back with the value.%0A   * @param %7BColorDef%7D color%0A   * @param %7Bfunction%7D listener%0A   * @public%0A   * @static%0A   */%0A  unlink( color, listener ) %7B%0A    assert && assert( ColorDef.isColorDef( color ), 'must be a colorDef' );%0A    if ( color instanceof Property ) %7B%0A      color.unlink( listener );%0A    %7D%0A  %7D,%0A%0A  // @returns %7Bstring%7Cnull%7D%0A  toCSS( color ) %7B%0A    assert && assert( ColorDef.isColorDef( color ), 'must be a colorDef' );%0A    return color === null ? null :%0A           typeof color === 'string' ? color :%0A           color instanceof Color ? color.toCSS() :%0A           ColorDef.toCSS( color.value );%0A  %7D,%0A%0A
   /**%0A  

Add ColorDef.link, unlink and toCSS, see https://github.com/phetsims/bamboo/issues/16