/**
 * @file mixins/stateful.js
 * @module stattlich
 * /
importiere {isEvented} aus '. /event ';
import * as Obj from '../utils/obj';

/**
 * Enthält Methoden, die einem übergebenen Objekt Zustandskraft verleihen
 * zu {@link module:stateful}.
 *
 * @mixin StatefulMixin
 * /
const StatefulMixin = {

  /**
   * Ein Hash, der beliebige Schlüssel und Werte enthält, die den Zustand von repräsentieren
   * das Objekt.
   *
   * @Typ {Objekt}
   * /
  Bundesstaat: {},

  /**
   * Legt den Zustand eines Objekts fest, indem ihr es mutiert
   * {@link module:stateful~statefulMixin.state|State} -Objekt an Ort und Stelle.
   *
   * @fires Modul: Stateful~StatefulMix in #statechanged
   * @param {Object|Funktion} StateUpdates
   * Ein neuer Satz von Eigenschaften, die in den Plugin-Status übernommen werden sollen.
   * Kann ein einfaches Objekt oder eine Funktion sein, die ein einfaches Objekt zurückgibt.
   *
   * @return {Object|undefined}
   * Ein Objekt, das eingetretene Änderungen enthält. Wenn sich nichts ändert
   * ist aufgetreten, gibt `undefined` zurück.
   * /
  setState (stateUpdates) {

    //Unterstützt die Bereitstellung des `StateUpdates` -Status als Funktion.
    if (typeofStateUpdates === 'Funktion') {
      stateUpdates = stateUpdates ();
    }

    lass dich ändern;

    obj.each (stateUpdates, (Wert, Schlüssel) => {

      //Notiere die Änderung, wenn der Wert von dem abweicht, der in der
      //aktueller Status.
      wenn (this.state [key]! == Wert) {
        Änderungen = Änderungen || {};
        ändert [Schlüssel] = {
          von: this.state [key],
          bis: Wert
        };
      }

      this.state [Schlüssel] = Wert;
    });

    //Löse „statechange“ nur aus, wenn es Änderungen gab UND wir einen Trigger haben
    //Funktion. Dadurch können wir nicht verlangen, dass das Zielobjekt ein
    //Ereignisobjekt.
    if (changes && isEvent (this)) {

      /**
       * Ein Ereignis, das an einem Objekt ausgelöst wird, das beides ist
       * {@link module:stateful|stateful} und {@link module:evented|evented}
       * zeigt an, dass sich sein Status geändert hat.
       *
       * @event Modul: Stateful~StatefulMix in #statechanged
       * @type {Objekt}
       * @property {Object} ändert sich
       * Ein Hash, der die Eigenschaften enthält, die geändert wurden und
       * die Werte, von denen sie `von` und `nach` geändert wurden.
       * /
      this.trigger({
        Änderungen,
        Typ: 'statechanged'
      });
    }

    Änderungen zurückgeben;
  }
};

/**
 * Wendet {@link module:Stateful~StatefulMixin|StatefulMixin} auf ein Ziel an
 * objekt.
 *
 * Wenn das Zielobjekt {@link module:evented|evented} ist und eine
 * `handleStateChanged` Methode, diese Methode wird automatisch an die gebunden
 * Das Ereignis `statechanged` an sich.
 *
 * @param {Object} Ziel
 * Das Objekt, das in einen Zustand gebracht werden soll.
 *
 * @param {Objekt} [DefaultState]
 * Ein Standardsatz von Eigenschaften zum Auffüllen der Eigenschaften des Objekts mit dem neuen Status
 * `staatliches` Eigentum.
 *
 * @return {Object}
 * Gibt das `Ziel` zurück.
 * /
function stateful (target, defaultState) {
  obj.assign (target, statefulMixin);

  //Das passiert nach dem Einmischen, weil wir den `state` ersetzen müssen
  //in diesem Schritt hinzugefügt.
  target.state = obj.assign ({}, target.state, defaultState);

  //Bindet die `handleStateChanged` Methode des Zielobjekts automatisch, falls sie existiert.
  if (typeof target.handleStateChanged === 'Funktion' && isEvent (target)) {
    target.on ('statechanged', target.handleStateChanged);
  }

  ziel zurückgeben;
}

Exportieren Sie den Standardstatus;