/**
 * @file mixins/stateful.js
 * @module 상태 저장
 */
'./evented'에서 {isEvented} 가져오기;
import * as Obj from '../utils/obj';

/**
 * 전달되는 개체에 상태 저장을 제공하는 메서드를 포함합니다.
 * {@link module:stateful}로.
 *
 * @mixin 스테이트풀믹신
 */
const StatefulMixin = {

  /**
   * 상태를 나타내는 임의의 키와 값을 포함하는 해시
   * 그 물체.
   *
   * @type {객체}
   */
  상태: {},

  /**
   * 개체를 변경하여 개체의 상태를 설정합니다.
   * {@link module:stateful~StatefulMixin.state|state} 개체가 제자리에 있습니다.
   *
   * @fires 모듈:stateful~StatefulMixin#statechanged
   * @param {객체|함수} stateUpdates
   * 플러그인 상태로 얕은 병합을 위한 새로운 속성 세트.
   * 일반 객체이거나 일반 객체를 반환하는 함수일 수 있습니다.
   *
   * @return {객체|정의되지 않음}
   * 발생한 변경 사항을 포함하는 개체입니다. 변경 사항이 없는 경우
   * 발생, `정의되지 않음`을 반환합니다.
   */
  setState(stateUpdates) {

    // `stateUpdates` 상태를 함수로 제공하는 것을 지원합니다.
    if (stateUpdates 유형 === '함수') {
      stateUpdates = stateUpdates();
    }

    변경하자;

    Obj.each(stateUpdates, (값, 키) => {

      // 값이 파일에 있는 것과 다른 경우 변경 사항을 기록
      // 현재 상태.
      if (this.state[key] !== 값) {
        변화 = 변화 || {};
        변경[키] = {
          출처: this.state[키],
          받는 사람: 값
        };
      }

      this.state[key] = 값;
    });

    // 변경 사항이 있고 트리거가 있는 경우에만 "statechange" 트리거
    // 기능. 이를 통해 대상 개체가
    // 이벤트 객체.
    만약 (변경 && isEvented(이)) {

      /**
       * 둘 다인 개체에서 트리거되는 이벤트
       * {@link module:stateful|stateful} 및 {@link module:evented|evented}
       * 상태가 변경되었음을 나타냅니다.
       *
       * @event 모듈:stateful~StatefulMixin#statechanged
       * @type {객체}
       * @property {객체} 변경
       * 변경된 속성을 포함하는 해시 및
       * `from` 및 `to`로 변경된 값.
       */
      this.trigger({
        변화,
        유형: '상태 변경됨'
      });
    }

    변경 사항을 반환합니다.
  }
};

/**
 * 대상에 {@link module:stateful~StatefulMixin|StatefulMixin} 적용
 * 물체.
 *
 * 대상 객체가 {@link module:evented|evented}이고
 * `handleStateChanged` 메소드, 해당 메소드는 자동으로
 * `statechanged` 이벤트 자체.
 *
 * @param {객체} 대상
 * stateful로 만들 객체.
 *
 * @param {객체} [defaultState]
 * 새로 상태 저장 개체를 채우는 기본 속성 집합
 * `상태` 속성.
 *
 * @return {객체}
 * '대상'을 반환합니다.
 */
함수 stateful(대상, defaultState) {
  Obj.assign(대상, StatefulMixin);

  // 이는 `state`를 교체해야 하기 때문에 혼합 후에 발생합니다.
  // 해당 단계에서 추가되었습니다.
  target.state = Obj.assign({}, target.state, defaultState);

  // 대상 객체의 `handleStateChanged` 메서드가 존재하는 경우 자동 바인딩합니다.
  if (typeof target.handleStateChanged === '함수' && isEvented(대상)) {
    target.on('statechanged', target.handleStateChanged);
  }

  반환 대상;
}

기본 스테이트풀 내보내기;