import IGame from '../Fabrique/IGame' ; interface IRecoveredState { l : string ; m : boolean ; sf : boolean ; } export default class SaveDataManager { private static instance : SaveDataManager ; private game : IGame ; private languageStr : string = 'undefined' ; private musicOn : boolean = true ; private sfxOn : boolean = true ; private callback : ( ) => void ; private callbackContext : any ; constructor ( game , callback ? , callbackContext ? ) { this . game = game ; this . callback = callback ; this . callbackContext = callbackContext ; this . game . storage . getItem ( STORAGE_KEY ) . then ( ( storedItem ) => { console . log ( 'SaveDataManager; constructor; loading save data; storedItem' , storedItem ) ; if ( storedItem === null || storedItem === undefined ) { this . languageStr = 'en' ; this . sfxOn = true ; this . musicOn = true ; this . save ( ) ; if ( this . callback && this . callbackContext ) { this . callback . call ( this . callbackContext ) ; } } else { this . restore ( ) ; } } ) ; } public static getInstance ( game ? , callback ? , callbackContext ? ) { if ( ! SaveDataManager . instance ) { SaveDataManager . instance = new SaveDataManager ( game , callback , callbackContext ) ; } return SaveDataManager . instance ; } public get language ( ) : string { return this . languageStr ; } public set language ( value ) { this . languageStr = value ; this . save ( ) ; this . game . i18n . setLanguage ( this . languageStr ) ; } public get music ( ) : boolean { return this . musicOn ; } public set music ( value ) { this . musicOn = value ; this . save ( ) ; } public get sfx ( ) : boolean { return this . sfxOn ; } public set sfx ( value ) { this . sfxOn = value ; this . save ( ) ; } /**
     * Saves the game's data to storage
     */ private save ( ) { let data = JSON . stringify ( < IRecoveredState > { l : this . languageStr , m : this . musicOn , sf : this . sfxOn } ) ; let hash = this . hash ( data ) ; this . game . storage . setItem ( STORAGE_KEY , data ) ; this . game . storage . setItem ( STORAGE_KEY + 'h' , hash ) ; } /**
     * Restores a save game from storage
     */ private restore ( ) { let storedData = this . game . storage . getItem ( STORAGE_KEY ) ; let storedHash = this . game . storage . getItem ( STORAGE_KEY + 'h' ) ; let data ; let hash ; Promise . all ( [ storedData , storedHash ] ) . then ( ( values ) => { data = values [ 0 ] || '' ; hash = values [ 1 ] || '0' ; if ( '' === data ) { return ; } if ( hash !== this . hash ( data ) ) { console . warn ( 'Incorrect save data.' ) ; return ; } if ( data && data !== '' ) { try { let save = JSON . parse ( data ) ; this . language = save . l ; this . musicOn = save . m ; this . sfxOn = save . sf ; this . game . i18n . setLanguage ( this . languageStr ) ; this . save ( ) ; } catch ( e ) { console . warn ( 'Unable to parse save game.' , e ) ; } } else { console . log ( 'No saved data.' ) ; } if ( this . callback && this . callbackContext ) { this . callback . call ( this . callbackContext ) ; } } ) ; } param data returns { string } private hash ( data ) { let hash = 0 , i , chr , len ; if ( data . length === 0 ) { return hash . toString ( ) ; } for ( i = 0 , len = data . length ; i < len ; i ++ ) { chr = data . charCodeAt ( i ) ; hash = ( ( hash << 5 ) - hash ) + chr ; hash |= 0 ; } return hash . toString ( ) ; } }