import Mixin from '../../../../object/mixin.js';
import '../../../meta/lib/meta.js';
import '../../../../../shared-chunks/mandatory-setter-CXNsxygN.js';
import { isDevelopingApp } from '@embroider/macros';
import '../../../../debug/index.js';
import '../../../../../@glimmer/destroyable/index.js';
import '../../../../../@glimmer/validator/index.js';
import '../../../../../@glimmer/manager/index.js';
import { g as get } from '../../../../../shared-chunks/cache-DtDz7X5V.js';
import '../../../../../shared-chunks/env-DxZ20QzS.js';
import { assert } from '../../../../debug/lib/assert.js';

/**
@module ember
*/

const ActionHandler = Mixin.create({
  mergedProperties: ['actions'],
  /**
    The collection of functions, keyed by name, available on this
    `ActionHandler` as action targets.
     These functions will be invoked when a matching `{{action}}` is triggered
    from within a template and the application's current route is this route.
     Actions can also be invoked from other parts of your application
    via `ActionHandler#send`.
     The `actions` hash will inherit action handlers from
    the `actions` hash defined on extended parent classes
    or mixins rather than just replace the entire hash, e.g.:
     ```app/mixins/can-display-banner.js
    import Mixin from '@ember/object/mixin';
     export default Mixin.create({
      actions: {
        displayBanner(msg) {
          // ...
        }
      }
    });
    ```
     ```app/routes/welcome.js
    import Route from '@ember/routing/route';
    import CanDisplayBanner from '../mixins/can-display-banner';
     export default Route.extend(CanDisplayBanner, {
      actions: {
        playMusic() {
          // ...
        }
      }
    });
     // `WelcomeRoute`, when active, will be able to respond
    // to both actions, since the actions hash is merged rather
    // then replaced when extending mixins / parent classes.
    this.send('displayBanner');
    this.send('playMusic');
    ```
     Within a Controller, Route or Component's action handler,
    the value of the `this` context is the Controller, Route or
    Component object:
     ```app/routes/song.js
    import Route from '@ember/routing/route';
     export default Route.extend({
      actions: {
        myAction() {
          this.controllerFor("song");
          this.transitionTo("other.route");
          ...
        }
      }
    });
    ```
     It is also possible to call `this._super(...arguments)` from within an
    action handler if it overrides a handler defined on a parent
    class or mixin:
     Take for example the following routes:
     ```app/mixins/debug-route.js
    import Mixin from '@ember/object/mixin';
     export default Mixin.create({
      actions: {
        debugRouteInformation() {
          console.debug("It's a-me, console.debug!");
        }
      }
    });
    ```
     ```app/routes/annoying-debug.js
    import Route from '@ember/routing/route';
    import DebugRoute from '../mixins/debug-route';
     export default Route.extend(DebugRoute, {
      actions: {
        debugRouteInformation() {
          // also call the debugRouteInformation of mixed in DebugRoute
          this._super(...arguments);
           // show additional annoyance
          window.alert(...);
        }
      }
    });
    ```
     ## Bubbling
     By default, an action will stop bubbling once a handler defined
    on the `actions` hash handles it. To continue bubbling the action,
    you must return `true` from the handler:
     ```app/router.js
    Router.map(function() {
      this.route("album", function() {
        this.route("song");
      });
    });
    ```
     ```app/routes/album.js
    import Route from '@ember/routing/route';
     export default Route.extend({
      actions: {
        startPlaying: function() {
        }
      }
    });
    ```
     ```app/routes/album-song.js
    import Route from '@ember/routing/route';
     export default Route.extend({
      actions: {
        startPlaying() {
          // ...
           if (actionShouldAlsoBeTriggeredOnParentRoute) {
            return true;
          }
        }
      }
    });
    ```
     @property actions
    @type Object
    @default null
    @public
  */

  /**
    Triggers a named action on the `ActionHandler`. Any parameters
    supplied after the `actionName` string will be passed as arguments
    to the action target function.
     If the `ActionHandler` has its `target` property set, actions may
    bubble to the `target`. Bubbling happens when an `actionName` can
    not be found in the `ActionHandler`'s `actions` hash or if the
    action target function returns `true`.
     Example
     ```app/routes/welcome.js
    import Route from '@ember/routing/route';
     export default Route.extend({
      actions: {
        playTheme() {
          this.send('playMusic', 'theme.mp3');
        },
        playMusic(track) {
          // ...
        }
      }
    });
    ```
     @method send
    @param {String} actionName The action to trigger
    @param {*} context a context to send with the action
    @public
  */
  send(actionName, ...args) {
    (isDevelopingApp() && !(!this.isDestroying && !this.isDestroyed) && assert(`Attempted to call .send() with the action '${actionName}' on the destroyed object '${this}'.`, !this.isDestroying && !this.isDestroyed));
    if (this.actions && this.actions[actionName]) {
      let shouldBubble = this.actions[actionName].apply(this, args) === true;
      if (!shouldBubble) {
        return;
      }
    }
    let target = get(this, 'target');
    if (target) {
      (isDevelopingApp() && !(typeof target.send === 'function') && assert(`The \`target\` for ${this} (${target}) does not have a \`send\` method`, typeof target.send === 'function'));
      target.send(...arguments);
    }
  }
});

export { ActionHandler as default };
