text: /**
   * @author       Richard Davey <rich@photonstorm.com>
   * @copyright    2019 Photon Storm Ltd.
   * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
   */
  
  var Class = require('../../utils/Class');
  var Factory = require('./Factory');
  var GetFastValue = require('../../utils/object/GetFastValue');
  var Merge = require('../../utils/object/Merge');
  var PluginCache = require('../../plugins/PluginCache');
  var SceneEvents = require('../../scene/events');
  var World = require('./World');
  
  /**
   * @classdesc
   * [description]
   *
   * @class ImpactPhysics
   * @memberof Phaser.Physics.Impact
   * @constructor
   * @since 3.0.0
   *
   * @param {Phaser.Scene} scene - [description]
   */
  var ImpactPhysics = new Class({
  
      initialize:
  
      function ImpactPhysics (scene)
      {
          /**
           * [description]
           *
           * @name Phaser.Physics.Impact.ImpactPhysics#scene
           * @type {Phaser.Scene}
           * @since 3.0.0
           */
          this.scene = scene;
  
          /**
           * [description]
           *
           * @name Phaser.Physics.Impact.ImpactPhysics#systems
           * @type {Phaser.Scenes.Systems}
           * @since 3.0.0
           */
          this.systems = scene.sys;
  
          /**
           * [description]
           *
           * @name Phaser.Physics.Impact.ImpactPhysics#config
           * @type {object}
           * @since 3.0.0
           */
          this.config = this.getConfig();
  
          /**
           * [description]
           *
           * @name Phaser.Physics.Impact.ImpactPhysics#world
           * @type {Phaser.Physics.Impact.World}
           * @since 3.0.0
           */
          this.world;
  
          /**
           * [description]
           *
           * @name Phaser.Physics.Impact.ImpactPhysics#add
           * @type {Phaser.Physics.Impact.Factory}
           * @since 3.0.0
           */
          this.add;
  
          scene.sys.events.once(SceneEvents.BOOT, this.boot, this);
          scene.sys.events.on(SceneEvents.START, this.start, this);
      },
  
      /**
       * This method is called automatically, only once, when the Scene is first created.
       * Do not invoke it directly.
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#boot
       * @private
       * @since 3.5.1
       */
      boot: function ()
      {
          this.world = new World(this.scene, this.config);
          this.add = new Factory(this.world);
  
          this.systems.events.once(SceneEvents.DESTROY, this.destroy, this);
      },
  
      /**
       * This method is called automatically by the Scene when it is starting up.
       * It is responsible for creating local systems, properties and listening for Scene events.
       * Do not invoke it directly.
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#start
       * @private
       * @since 3.5.0
       */
      start: function ()
      {
          if (!this.world)
          {
              this.world = new World(this.scene, this.config);
              this.add = new Factory(this.world);
          }
  
          var eventEmitter = this.systems.events;
  
          eventEmitter.on(SceneEvents.UPDATE, this.world.update, this.world);
          eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this);
      },
  
      /**
       * [description]
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#getConfig
       * @since 3.0.0
       *
       * @return {object} [description]
       */
      getConfig: function ()
      {
          var gameConfig = this.systems.game.config.physics;
          var sceneConfig = this.systems.settings.physics;
  
          var config = Merge(
              GetFastValue(sceneConfig, 'impact', {}),
              GetFastValue(gameConfig, 'impact', {})
          );
  
          return config;
      },
  
      /**
       * [description]
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#pause
       * @since 3.0.0
       *
       * @return {Phaser.Physics.Impact.World} The Impact World object.
       */
      pause: function ()
      {
          return this.world.pause();
      },
  
      /**
       * [description]
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#resume
       * @since 3.0.0
       *
       * @return {Phaser.Physics.Impact.World} The Impact World object.
       */
      resume: function ()
      {
          return this.world.resume();
      },
  
      /**
       * The Scene that owns this plugin is shutting down.
       * We need to kill and reset all internal properties as well as stop listening to Scene events.
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#shutdown
       * @private
       * @since 3.0.0
       */
      shutdown: function ()
      {
          var eventEmitter = this.systems.events;
  
          eventEmitter.off(SceneEvents.UPDATE, this.world.update, this.world);
          eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this);
  
          this.add.destroy();
          this.world.destroy();
  
          this.add = null;
          this.world = null;
      },
  
      /**
       * The Scene that owns this plugin is being destroyed.
       * We need to shutdown and then kill off all external references.
       *
       * @method Phaser.Physics.Impact.ImpactPhysics#destroy
       * @private
       * @since 3.0.0
       */
      destroy: function ()
      {
          this.shutdown();
  
          this.scene.sys.events.off(SceneEvents.START, this.start, this);
  
          this.scene = null;
          this.systems = null;
      }
  
  });
  
  PluginCache.register('ImpactPhysics', ImpactPhysics, 'impactPhysics');
  
  module.exports = ImpactPhysics;
  