import renderingData from '../../utils/rendering-data/featureTypeData' ; import { FeatureState , FeatureType , ActionType , SubElementNameType , objType , ElementNameType , SubElementType , StyleType , } from '../common/type' ; import { getDefaultFeature , getDefaultStyle } from './properties' ; import { INIT , SET , SET_WHOLE , REPLACE_FEATURE , REPLACE_WHOLE , INIT_COLORS , } from './action' ; import { checkStyleIsChanged , checkFeatureIsChanged } from './compareStyle' ; import { combineElement } from './manageCategories' ; interface ReducerType { ( state , action ) : FeatureState ; } export default function getReducer ( IDX ) { const featureName = renderingData [ IDX ] . typeKey ; const subFeatures = [ 'all' , ... ( renderingData [ IDX ] . subFeatures ?. map ( ( v ) => v . key ) as string [ ] ) , ] ; const initialState = subFeatures . reduce ( ( acc , cur ) => { acc [ cur ] = getDefaultFeature ( { feature : featureName , subFeature : cur , } ) ; return acc ; } , { } ) ; return function reducer ( state = initialState , action ) : FeatureState { switch ( action . type ) { case INIT : return initialState ; case REPLACE_WHOLE : return action . payload [ featureName ] ; case SET : { const { feature , subFeature , element , subElement , style , } = action . payload ; if ( feature !== featureName ) return state ; const defaultStyle = getDefaultStyle ( action . payload ) ; style . isChanged = checkStyleIsChanged ( { defaultStyle , style } ) ; const newState = JSON . parse ( JSON . stringify ( state ) ) ; const newFeature = newState [ subFeature as string ] ; let prevIsChanged ; if ( element === ElementNameType . labelIcon ) { prevIsChanged = newFeature [ element ] ?. isChanged ; newFeature [ element ] = style ; } else { prevIsChanged = ( newFeature [ element ] as SubElementType ) [ subElement as SubElementNameType ] . isChanged ; ( newFeature [ element ] as SubElementType ) [ subElement as SubElementNameType ] = style ; } if ( prevIsChanged !== style . isChanged ) { delete ( newFeature as objType ) . isChanged ; const featureIsChanged = checkFeatureIsChanged ( newFeature ) ; newFeature . isChanged = featureIsChanged ; } return newState ; } case REPLACE_FEATURE : case SET_WHOLE : { if ( action . type === REPLACE_FEATURE && ! action . payload [ featureName ] ) return state ; const inputStyle = action . payload [ featureName ] ; const updateStyle = JSON . parse ( JSON . stringify ( initialState ) ) ; if ( ! inputStyle ) return updateStyle ; const subFeatures = Object . keys ( inputStyle ) ; subFeatures . forEach ( ( subFeature ) => { const newFeature = combineElement ( { elementStyle : inputStyle [ subFeature ] , initialElementStyle : updateStyle [ subFeature ] , } ) ; updateStyle [ subFeature ] = { ... newFeature , isChanged : checkFeatureIsChanged ( newFeature ) , } ; } ) ; return updateStyle ; } case INIT_COLORS : { const { feature , element , subElement } = action . payload ; if ( feature !== featureName ) return state ; const newState = JSON . parse ( JSON . stringify ( state ) ) ; Object . keys ( newState ) . forEach ( ( subFeature ) => { const defaultStyle = getDefaultStyle ( { feature , subElement , element , subFeature , } ) ; if ( element === ElementNameType . labelIcon ) { const style = newState [ subFeature ] [ element ] as StyleType ; style . color = defaultStyle . color ; style . isChanged = checkStyleIsChanged ( { defaultStyle , style } ) ; return ; } const style = ( newState [ subFeature ] [ element ] as SubElementType ) [ subElement ] ; style . color = defaultStyle . color ; style . isChanged = checkStyleIsChanged ( { defaultStyle , style } ) ; } ) ; delete ( newState . all as objType ) . isChanged ; newState . all . isChanged = checkFeatureIsChanged ( newState . all ) ; return newState ; } default : return state ; } } ; }