import { MapLike } from "map-like" ; import { Store } from "../Store" ; import { shouldStateUpdate } from "./StoreGroupUtils" ; /**
 * Warning: check immutability state between prevState and nextState.
 * If the store call `Store#emitChange()` and the state of store is not changed, show warning
 * https://github.com/almin/almin/issues/151
 * https://github.com/almin/almin/pull/205
 */ const warningIfChangingStoreIsNotImmutable = ( store , prevState , nextState ) => { const isStateChanged = shouldStateUpdate ( store , prevState , nextState ) ; if ( isStateChanged ) { return ; } console . error ( `Warning(Store): ${ store . name } does call emitChange(). 
But, this store's state is not changed.
Store's state should be immutable value.
Prev State:` , prevState , `Next State:` , nextState ) ; } ; /**
 * Warning: check immutability of the `store`'s state
 * If the store's `state` property is directly modified, show warning message.
 * We recommenced to use `Store#setState` for updating state of store.
 * https://github.com/almin/almin/issues/151
 */ const warningIfStatePropertyIsModifiedDirectly = ( store , prevState , nextState ) => { if ( ! store . hasOwnProperty ( "state" ) ) { return ; } if ( store . state !== nextState ) { return ; } const isStateReferenceReplaced = prevState !== nextState ; const isStateUpdated = shouldStateUpdate ( store , prevState , nextState ) ; const isStateReplacedButShouldNotUpdate = isStateReferenceReplaced && ! isStateUpdated ; if ( isStateReplacedButShouldNotUpdate ) { console . error ( `Warning(Store): ${ store . name }#state property is replaced by different value directly, but this changes **does not** reflect to view.
Because, ${ store . name }#shouldStateUpdate(prevState, newState) has returned **false**.
It means that you have replaced store's state by new state directly, but it is not correct way.

NG: assign newState to state property directly
    
    this.state = newState;

The mismatch is occurred between ${ store . name }#state property and shouldStateUpdate.
You should use \`Store#setState\` method for updating store's state.

OK: update state via setState

    this.setState(newState);
    
    // OR

    // setState alias
    if(this.shouldStateUpdate(this.state, newState)){
        this.state = newState;
    }
` , "prevState" , prevState , "nextState" , nextState ) ; } } ; /**
 * Check the usage of Store#emitChange.
 * If the store call `Store#emitChange()` but the state of store is not changed, show warning.
 * https://github.com/almin/almin/issues/151
 * https://github.com/almin/almin/pull/205
 */ export class StoreGroupEmitChangeChecker { private _emitChangeStateCacheMap = new MapLike < Store < any > , any > ( ) ; /**
     * mark `store` as `emitChange`ed store in a UseCase life-cycle
     *
     * Warning: Show warning message if the `store`'s state is not changed.
     */ mark ( store , cachedPrevState , nextState ) { const previousEmitChangedState = this . _emitChangeStateCacheMap . get ( store ) ; const prevState = previousEmitChangedState || cachedPrevState ; warningIfChangingStoreIsNotImmutable ( store , prevState , nextState ) ; this . _emitChangeStateCacheMap . set ( store , nextState ) ; } /**
     * Is this `store` marked by the checker?
     */ isMarked ( store ) { return this . _emitChangeStateCacheMap . has ( store ) ; } /**
     * unMark `store` at end of a useCase life-cycle
     * When the nextState is confirmed, should call it.
     */ unMark ( store ) { this . _emitChangeStateCacheMap . delete ( store ) ; } /**
     * Warning: Show warning message if the `store`'s state is modified directly.
     * We recommenced to use `Store#setState` for updating state of store.
     *
     * ## Example
     *
     * ```js
     * class MyStore extends Store {
     *  receivePayload(){
     *      // direct modified
     *      this.state = { value: "next" }
     *  }
     * }
     * ```
     */ warningIfStatePropertyIsModifiedDirectly ( store , prevState , nextState ) { if ( ! this . isMarked ( store ) ) { warningIfStatePropertyIsModifiedDirectly ( store , prevState , nextState ) ; } } }