import { STATUS , ListDiff , ListData , DiffStatus } from "./model" ;
import { isEqual } from "./utils" ;
function formatSingleListDiff (
listData : ListData [ ] ,
status : DiffStatus
) : ListDiff {
return {
type : "list" ,
status ,
diff : listData.map ( ( data : ListData , i ) = > ( {
value : data ,
prevIndex : status === STATUS . ADDED ? null : i ,
newIndex : status === STATUS . ADDED ? i : null ,
indexDiff : null ,
status ,
} ) ) ,
} ;
}
function getListStatus ( listDiff : ListDiff [ "diff" ] ) : DiffStatus {
return listDiff . some ( ( value ) = > value . status !== STATUS . EQUAL )
? STATUS . UPDATED
: STATUS . EQUAL ;
}
export const getListDiff = (
prevList : ListData [ ] | undefined | null ,
nextList : ListData [ ] | undefined | null
) : ListDiff = > {
if ( ! prevList && ! nextList ) {
return {
type : "list" ,
status : STATUS.EQUAL ,
diff : [ ] ,
} ;
}
if ( ! prevList ) {
return formatSingleListDiff ( nextList as ListData , STATUS . ADDED ) ;
}
if ( ! nextList ) {
return formatSingleListDiff ( prevList as ListData , STATUS . DELETED ) ;
}
const diff : ListDiff [ "diff" ] = [ ] ;
nextList . forEach ( ( nextValue , i ) = > {
const prevIndex = prevList . findIndex ( ( prevValue ) = >
isEqual ( prevValue , nextValue )
) ;
const indexDiff = prevIndex === - 1 ? null : i - prevIndex ;
if ( indexDiff === 0 ) {
return diff . push ( {
value : nextValue ,
prevIndex ,
newIndex : i ,
indexDiff ,
status : STATUS.EQUAL ,
} ) ;
}
if ( prevIndex === - 1 ) {
return diff . push ( {
value : nextValue ,
prevIndex : null ,
newIndex : i ,
indexDiff ,
status : STATUS.ADDED ,
} ) ;
}
return diff . push ( {
value : nextValue ,
prevIndex ,
newIndex : i ,
indexDiff ,
status : STATUS.MOVED ,
} ) ;
} ) ;
prevList . forEach ( ( prevValue , i ) = > {
if ( ! nextList . some ( ( nextValue ) = > isEqual ( nextValue , prevValue ) ) ) {
return diff . splice ( i , 0 , {
value : prevValue ,
prevIndex : i ,
newIndex : null ,
indexDiff : null ,
status : STATUS.DELETED ,
} ) ;
}
} ) ;
return {
type : "list" ,
status : getListStatus ( diff ) ,
diff ,
} ;
} ;