/**
 * @file mixins/stateful.js
 * @module 有狀態
 */
從 './evented' 導入 {isEvented};
從 '../utils/obj' 導入 * 作為 Obj;

/**
 * 包含為傳遞的對象提供狀態的方法
 * 到 {@link module:stateful}。
 *
 * @mixin StatefulMixin
 */
const StatefulMixin = {

  /**
   * 包含代表狀態的任意鍵和值的散列
   * 物體。
   *
   * @type {對象}
   */
  狀態: {},

  /**
   * 通過改變對象的狀態來設置對象的狀態
   * {@link module:stateful~StatefulMixin.state|state} 對像到位。
   *
   * @fires 模塊:stateful~StatefulMixin#statechanged
   * @param {Object|Function} 狀態更新
   * 一組新的屬性淺合併到插件狀態。
   * 可以是普通對像或返回普通對象的函數。
   *
   * @return {對象|未定義}
   * 包含已發生更改的對象。如果沒有變化
   * 發生,返回 `undefined`。
   */
  設置狀態(狀態更新){

    // 支持將 `stateUpdates` 狀態作為函數提供。
    如果(typeof stateUpdates ==='函數'){
      stateUpdates = stateUpdates();
    }

    讓改變;

    Obj.each(stateUpdates, (value, key) => {

      // 如果值與中的值不同,則記錄更改
      // 當前狀態。
      如果 (this.state[key] !== value) {
        變化=變化|| {};
        變化[鍵] = {
          來自:this.state[key],
          至:價值
        };
      }

      this.state[鍵] = 值;
    });

    // 只有在有變化並且我們有觸發器時才觸發“statechange”
    // 功能。這允許我們不要求目標對像是一個
    // 事件對象。
    如果(改變&& isEvented(這個)){

      /**
       * 在一個對像上觸發的事件既是
       * {@link module:stateful|stateful} 和 {@link module:evented|evented}
       * 表示它的狀態已經改變。
       *
       * @event 模塊:stateful~StatefulMixin#statechanged
       * @type {對象}
       * @property {Object} 變化
       * 包含更改的屬性的散列和
       * 它們被更改為“from”和“to”的值。
       */
      這個。觸發({
        變化,
        類型:'狀態改變'
      });
    }

    返回更改;
  }
};

/**
 * 將 {@link module:stateful~StatefulMixin|StatefulMixin} 應用於目標
 * 目的。
 *
 * 如果目標對像是 {@link module:evented|evented} 並且有一個
 * `handleStateChanged` 方法,該方法將自動綁定到
 * `statechanged` 事件本身。
 *
 * @param {Object} 目標
 * 要成為有狀態的對象。
 *
 * @param {對象} [默認狀態]
 * 用於填充新狀態對象的一組默認屬性
 * `state` 屬性。
 *
 * @return {對象}
 * 返回“目標”。
 */
函數狀態(目標,默認狀態){
  Obj.assign(target, StatefulMixin);

  // 這發生在混入之後,因為我們需要替換 `state`
  // 在該步驟中添加。
  target.state = Obj.assign({}, target.state, defaultState);

  // 如果目標對象存在,則自動綁定目標對象的 `handleStateChanged` 方法。
  if (typeof target.handleStateChanged === 'function' && isEvented(target)) {
    target.on('狀態改變', target.handleStateChanged);
  }

  返回目標;
}

導出默認狀態;