import { Observable , of } from 'rxjs' ; import { catchError , map , share } from 'rxjs/operators' ; import { History } from 'history' ; import { IStateStorage } from './types' ; import { createOsdUrlControls , getStateFromOsdUrl , setStateToOsdUrl , } from '../../state_management/url' ; /**
 * OsdUrlStateStorage is a state storage for  syncState utility which:
 *
 * 1. Keeps state in sync with the URL.
 * 2. Serializes data and stores it in the URL in one of the supported formats:
 *   * Rison encoded.
 *   * Hashed URL: In URL we store only the hash from the serialized state, but the state itself is stored in sessionStorage. See OpenSearch Dashboards's `state:storeInSessionStorage`
 *     advanced option for more context.
 * 3. Takes care of listening to the URL updates and notifies state about the updates.
 * 4. Takes care of batching URL updates to prevent redundant browser history records.
 *
 * TODO: Update link
 *  https public export interface IOsdUrlStateStorage extends IStateStorage { set : < State > ( key : string , state : State , opts ? : { replace : boolean ; } ) => Promise < string | undefined > ; get : < State = unknown > ( key : string ) => State | null ; change$ : < State = unknown > ( key : string ) => Observable < State | null > ; /**
     * cancels any pending url updates
     */ cancel : ( ) => void ; param opts returns flush : ( opts ? : { replace ? : boolean ; } ) => boolean ; } /**
 * Creates  IOsdUrlStateStorage state storage
 *  returns -  IOsdUrlStateStorage public export const createOsdUrlStateStorage = ( { useHash = false , history , onGetError , onSetError , } = { useHash : false , } ) : IOsdUrlStateStorage => { const url = createOsdUrlControls ( history ) ; return { set : < State > ( key , state , { replace = false } = { replace : false } ) => { return url . updateAsync ( ( currentUrl ) => { try { return setStateToOsdUrl ( key , state , { useHash } , currentUrl ) ; } catch ( error ) { if ( onSetError ) onSetError ( error ) ; } } , replace ) ; } , get : ( key ) => { try { return getStateFromOsdUrl ( key , url . getPendingUrl ( ) ) ; } catch ( e ) { if ( onGetError ) onGetError ( e ) ; return null ; } } , change$ : < State > ( key ) => new Observable ( ( observer ) => { const unlisten = url . listen ( ( ) => { observer . next ( ) ; } ) ; return ( ) => { unlisten ( ) ; } ; } ) . pipe ( map ( ( ) => getStateFromOsdUrl < State > ( key ) ) , catchError ( ( error ) => { if ( onGetError ) onGetError ( error ) ; return of ( null ) ; } ) , share ( ) ) , flush : ( { replace = false } = { } ) => { return ! ! url . flush ( replace ) ; } , cancel ( ) { url . cancel ( ) ; } , } ; } ;