function nullthrows(nullable, error, onlyCheckForNull = false) {
    if (onlyCheckForNull && nullable === null) {
        throw error
    }

    if (nullable === null || nullable === undefined) {
        throw error
    }

    return nullable
}

class AutoStorageNullValueError extends Error {
    autoStorageKey = ""
    constructor(autoStorageKey) {
        const message = `Value for key ${autoStorageKey} is null`
        super(message)
        this.name = AutoStorageNullValueError.name
        this.autoStorageKey = autoStorageKey
    }
}

/**
 * abstracts parts of localStorage to make dev life great again!
 */
class AutoStorage {
    static STORAGE_TYPE = {
        MEMORY: "memory",
        SESSION: "session",
        LOCAL: "local",
    }
    /** used when we do not want to persist data in local storage. */
    unstableStorage = {}

    /** remember the object's name. used to add new items after objectn creation*/
    namespace = null

    /** used to encrypt and decrypt values writen to local storage or session storage*/
    encryptionKey = null // <---- remove

    /**
     * Used for custom handling when getting an object from AutoStorage
     * @callback validateOnGet
     * @param {any} value
     */
    /**
     * Used for custom handling when setting an object from AutoStorage
     * @callback validateOnSet
     * @param {any} value
     */

    /**
     * @typedef { ({
     * canBeEmpty: boolean,
     * storageType: "memory"|"session"|"local",
     * defaultValue: *,
     * }|undefined)} Settings
     */

    /** @type Settings */
    settings = {}

    /**
     * a object that stores the name of the getter/setter to then act upon it. 
     * example: `BookStorage.bookSettings.actOn.deploymentId.updateStorageType("local")`
     * will update the storage type to "local" for the attribute `deploymentId`.  
     */
    actOn = {}

    /**
     * @param {string} namespace the name of the storage object. This is used to keep track of 
     * attributes with the same name but in different AutoStorage objects.
     * @param {{[string]: {
     *  settings: Settings, 
     *  validateOnGet: validateOnGet,
     *  validateOnSet: validateOnSet,
     * }}} obj an array of tuples, where the first 
     * value is the name of getter / setter of the attribute, and the second value is a settings 
     * object which can be undefined if the attribute using the default settings.
     */
    constructor(namespace, obj) {
        const settingsForTheClassSettings = { storageType: AutoStorage.STORAGE_TYPE.LOCAL, encrypt: false, localOnly: true }
        const settingsKey = `${namespace}.__AutoStorage_Settings__` // lets make this a function

        this.namespace = namespace
        for (const [name, params] of Object.entries(obj)) {
            this.#initializeItem(namespace, name, params, settingsForTheClassSettings, settingsKey)
        }
        // persist the settings object in local sotrage
        this.setItem(settingsKey, JSON.stringify(this.settings), settingsForTheClassSettings)
    }

    /**
     * Private. Sets up one key-value pair.
     * @param {string} namespace 
     * @param {string} name 
     * @param {object} params  
     * @param {string} settingsForTheClassSettings  
     * @param {string} params  
     */
    #initializeItem(namespace, name, params, settingsForTheClassSettings, settingsKey) {
        //log("at initializeItem",namespace, name, params,settingsForTheClassSettings,settingsKey)
        const savedSettings = this.getItem(settingsKey, settingsForTheClassSettings, undefined, true) || {}
        this.settings[name] = savedSettings[name] || params.settings || {}
        const key = `${namespace}.${name}`

        if (this[name]) { throw new CannotInitializeItemThatAlreadyExsists(name) }

        // creating the getter/setter
        this[name] = (value) => {
            if (value === undefined) {
                // getting the value stored for this `name`
                try {
                    const value = this.getItem(key, this.settings[name], params.validateOnGet)
                    return value
                } catch (error) {
                    if (error instanceof AutoStorageNullValueError) {
                        if (this.settings[name]?.canBeEmpty) {
                            return null
                        }
                    }
                    throw error
                }
            } else {
                // setting the value stored for this name
                return this.setItem(key, JSON.stringify(value), this.settings[name], params.validateOnSet)
            }
        }

        this.actOn[name] = {
            updateStorageType: (storageTypeString) => {

                // get the value BEFORE we remove it (and it's key)
                try {
                    //log("name", name)
                    const valueFromOldStorageSystem = this[name]()
                    this.removeItem(key, this.settings[name])
                    this.settings[name].storageType = storageTypeString
                    this[name](valueFromOldStorageSystem)
                } catch (error) {
                    if (!(error instanceof AutoStorageNullValueError)) {
                        throw error
                    }
                } finally {
                    this.settings[name].storageType = storageTypeString
                    // now we change the storage type to what we want. Then 
                    // we call the setter as normal
                    this.setItem(settingsKey, JSON.stringify(this.settings), settingsForTheClassSettings)
                }


            },
            delete: () => this.removeItem(key, this.settings[name]),
        }

        if (this.settings[name]?.defaultValue !== undefined) {
            try {
                this.getItem(key, this.settings[name], params.validateOnGet) // if this throws then we need to put in the default value
            } catch (error) {
                if (error instanceof AutoStorageNullValueError) {
                    this[name](this.settings[name]?.defaultValue) // putting in the default value
                } else {
                    throw error
                }
            }
        }
    }

    /**
    * deletes all variables, initializes those with default values
    *
    */
    reset() { // <---- remove
        //log("at reset", this.settings)
        for (const key of Object.keys(this.actOn)) {
            if (this.settings[key].defaultValue !== undefined) {
                //debugger
                this.setItem(this.namespace + "." + key, JSON.stringify(this.settings[key].defaultValue), this.settings[key])
            } else {
                this.actOn[key].delete()
            }
            //log(key, this.actOn[key])
            //this.actOn[key].updateStorageType(storageType)
        }
    }

    /**
     * Private. Gets the the given key-value.
     * @param {string} key 
     * @param {Settings} settings 
     * @param {validateOnGet} validateOnGet  
     * @param {boolean} doNotThrowIfNull only for internal use 
     * @returns 
     */
    getItem(key, settings, validateOnGet = undefined, doNotThrowIfNull = false) {
        const item = this.getItemFromStorage(key, settings)
        return this.validateItem(item, key, settings, validateOnGet, doNotThrowIfNull)
    }

    getItemFromStorage(key, settings) {
        let item
        switch (settings?.storageType) {
            case AutoStorage.STORAGE_TYPE.MEMORY:
                item = this.unstableStorage[key]
                break
            case AutoStorage.STORAGE_TYPE.SESSION:
                item = sessionStorage.getItem(key)
                break
            default:
                item = localStorage.getItem(key)
                break
        }
        return item
    }

    validateItem(item, key, settings, validateOnGet = undefined, doNotThrowIfNull = false) {
        if (typeof validateOnGet === 'function') {
            // we can let the developer decide how to handle getting an item
            item = JSON.parse(item)
            validateOnGet(item)
            return item
        } else if (doNotThrowIfNull) {
            // this is only when we explicity do not care what the value is
            try {
                return JSON.parse(item)
            } catch (e) {
                //log("returning default value")
                return settings.defaultValue
            }
        } else {
            // otherwise, use the default validation
            const raw_value = nullthrows(item, new AutoStorageNullValueError(key))
            // now try to parse the value, if it fails, the token has not decrypted the value correctly.
            try {
                return JSON.parse(raw_value)
            } catch (e) {
                //log("--returning default")
                return settings.defaultValue
            }

        }
    }

    /**
     * Private. Sets the the given key-value.
     * @param {string} key 
     * @param {string} rawValue json string of value
     * @param {Settings} settings 
     * @param {validateOnSet} validateOnSet 
     */
    setItem(key, value, settings, validateOnSet) {
        if (typeof validateOnSet === "function") {
            validateOnSet(value)
        }
        log("setItem====", key, value, typeof settings.onSet, settings)
        if(typeof settings.onSet==="function"){
            log('Setting onise stuff')
            settings.onSet(value)
        }

        switch (settings?.storageType) {
            case AutoStorage.STORAGE_TYPE.MEMORY:
                this.unstableStorage[key] = value
                break
            case AutoStorage.STORAGE_TYPE.SESSION:
                sessionStorage.setItem(key, value)
                break
            default:
                localStorage.setItem(key, value)
                break
        }

        return value
    }

    /**
     * Removes the given key-value.
     * @param {string} key 
     * @param {Settings} settings 
     * @returns 
     */
    removeItem(key, settings) {
        switch (settings?.storageType) {
            case AutoStorage.STORAGE_TYPE.MEMORY:
                delete this.unstableStorage[key]
                return
            case AutoStorage.STORAGE_TYPE.SESSION:
                return sessionStorage.removeItem(key)
            default:
                return localStorage.removeItem(key)
        }
    }
    /**
     * Report if a key exists.
     * @param {string} name 
     * @returns
     */
    exists(name) {
        return this[name] !== undefined
    }
    /**
     * adds a new key-value.
     * @param {string} name 
     * @param {object} params  
     */
    addItem(name, params = { settings: {} }) {
        const settingsForTheClassSettings = { storageType: AutoStorage.STORAGE_TYPE.LOCAL, encrypt: false, localOnly: true }
        const settingsKey = `${this.namespace}.__AutoStorage_Settings__`
        //log(name, params)
        const new_params = JSON.parse(JSON.stringify(params))
        if (!new_params.settings.storageType) {
            if (this.isPrivateComputer()) {
                new_params.settings.storageType = AutoStorage.STORAGE_TYPE.LOCAL
            } else {
                new_params.settings.storageType = AutoStorage.STORAGE_TYPE.SESSION
            }
        }
        //log("new params", new_params)
        this.#initializeItem(this.namespace, name, new_params, settingsForTheClassSettings, settingsKey)

        // persist the settings object in local sotrage
        this.setItem(settingsKey, JSON.stringify(this.settings), settingsForTheClassSettings)

    }

    updateStorageType(storageType) {
        //moves all items to the specified storage time (e.g. local or session)
        debug()
        for (const key of Object.keys(this.actOn)) {
            this.actOn[key].updateStorageType(storageType)
        }
    }

    getKeys() {
        //returns the set of keys in the namespace
        const keys = []
        for (const key of Object.keys(this.actOn)) {
            keys.push(key)
        }
        return keys
    }
}

class SecretStorage extends AutoStorage {
    constructor(namespace, obj, encryptionKey) {
        super(namespace, obj)
        this.encryptionKey = JSON.parse(sessionStorage.getItem(namespace + ".token")) || JSON.parse(localStorage.getItem(namespace + ".token")) // <---- remove

        //log("setting encrytion key in constructopr", encryptionKey)

        if (this.encryptionKey === 'null' || this.encryptionKey === null) { // <---- remove
            // no token, this is a new login, use the default token
            this.encryptionKey = ncrypt("Shall we sin on still impenitent and incorrigible?", encryptionKey)
        }
    }

    /**
     * reports if the current submitted encryption key is able to decrypt values in the namespace.
     * @param {string} encryptionKey 
     * @returns 
     */
    authenticate() {
        return (dcrypt(this.canary(), this.token()) === "logged in")
    }
    /**
     * reports if the current encryption key is able to decrypt values in the namespace.
     * @returns 
     */
    loggedIn() {
        return (this.authenticate())
    }
    /**
     * reports if the current password sent is is able to decrypt the canary.
     * @returns 
     */
    login(password) {
        // deprecated--hadnling login outsite this class
        const temp_token = ncrypt("Shall we sin on still impenitent and incorrigible?", password)
        if (dcrypt(this.canary(), temp_token) === "logged in") {
            this.token(temp_token)
            return true
        }
        return false
    }

    /**
    * Logs the user out by deleting the token.
    */
    logout() {

        // if we are logintype is local, we need to write all of bookStorage to local storage
        const current_login_type=this.loginType()

        if(current_login_type==="local"){
            //const data_package=ncrypt(JSON.stringify(this.settings),this.encryptionKey)
            const data_package=ncrypt(JSON.stringify(bookstorage_to_object(false)),this.encryptionKey)
            
            localStorage.clear()
            sessionStorage.clear()
            localStorage.setItem("loginPackage", data_package)
        }else{
            //clear out all local and session storage
            localStorage.clear()
            sessionStorage.clear()
        }
        localStorage.setItem("loginType",current_login_type)


        // localStorage.removeItem(this.namespace + ".token")
        // localStorage.removeItem(this.namespace + ".gasToken")
        // // clear anything that is session storage
        // for (const [key, settings] of Object.entries(this.settings)) {
        //     if (settings.storageType === AutoStorage.STORAGE_TYPE.SESSION) {
        //         this.removeItem(this.namespace + "." + key, settings)
        //     }
        // }
        window.location.reload()
    }

    changeEncryptionKey(new_encryption_key) {
        //updates the encryption key and transcodes all stored values
        const plain_text_values = {}
        for (const key of Object.keys(this.actOn)) {
            let value = null
            try {
                value = this[key]()
            } catch (e) {
                // throws if null, which is fine is this context
            }

            if (value !== null) {
                //log(this.settings[key], key, value)
                plain_text_values[key] = value
            }
        }

        this.encryptionKey = ncrypt("Shall we sin on still impenitent and incorrigible?", new_encryption_key)
        for (const [key, val] of Object.entries(plain_text_values)) {
            //log("-->",key, val, this.settings[key], this.encryptionKey)
            if (key !== "token") {
                this[key](val)
            }
        }

        this.token(this.encryptionKey)
        this.canary(ncrypt("logged in", this.encryptionKey))
    }

    getItemFromStorage(key, settings) {
        const item = super.getItemFromStorage(key, settings)
        if (settings.encrypt !== false) { // explict check against false, that means unless it is set to false we plan to encrypt or decrypt
            return dcrypt(item, this.encryptionKey + key)
        }
        return item
    }

    setItem(key, rawValue, settings, validateOnSet) {

        if (rawValue === this.getItemFromStorage(key, settings)) {
            // the property already has this value
            return false
        }

        const value = (
            settings.encrypt === false
                ? rawValue
                : ncrypt(rawValue, this.encryptionKey + key)
        )

        const returnValue = super.setItem(key, value, settings, validateOnSet) // calls the autoStorage method 
        // if the token was updated, we need to update the encryption key
        if (key === this.namespace + ".token") {
            this.encryptionKey = JSON.parse(rawValue)
        }

        return true
    }
}

class SuperStorage extends SecretStorage {


    constructor(namespace, obj, encryptionKey) {
        super(namespace, obj, encryptionKey)
        this.batch = {}
        this.timeoutId = null
    }

    getGasToken() {
        let gas_token
        try {
            gas_token = this.gasToken()
        } catch (e) {
            gas_token = null
        }
        return gas_token
    }

    setItem(key, rawValue, settings, validateOnSet) {
        // synchonusly write to the local storage
        const did_set = super.setItem(key, rawValue, settings, validateOnSet)
        // we have written to local storage, now write to server if configured

        if (!settings.localOnly && did_set) {
            this.debouncedServerPost({ id: key.split(".")[1], value: rawValue })
        }

        return this
    }

    debouncedServerPost(data){
        if(this.batch!==undefined){
            // Gove and Eli are not sure why this.batch is undefined when it is starting up
            // however, without this if statement, the page breaks when first loaded
            this.batch[data.id] = data
            this.internalDebounce(Object.values(this.batch))
        }
    }

    internalDebounce = debounce(async (batch) => {
        const json_data = await server_post({
            "mode": "property",
            "token": this.getGasToken(),
            "action": "set",
            "key": "book_storage",
            "dataArray": batch,
        })
        this.batch = {}
        if (json_data?.status === "success") {
            return json_data
        } else {
            throw json_data
        }

    }, 2000 /* <--- this function will only be called x milliseconds after not being called. */)
}


const BookStorage = new SuperStorage("BookStorage", {
    aiType: { settings: { defaultValue: 'gpt', storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    dbType: { settings: { defaultValue: 'sqlite', storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    bookContents: { settings: { defaultValue: 'toc-json', storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    canary: { settings: { defaultValue: 'k7brL/5r8xfk9Beh+35EDW4=', encrypt: false, storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true } },
    courseCode: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    currentPage: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true } },
    deploymentId: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true } },
    dwToken: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    gasToken: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true } },
    isPrivateComputer: {settings: {storageType: AutoStorage.STORAGE_TYPE.SESSION,defaultValue: true,encrypt: false,localOnly: true}},
    localCanary: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true } },
    loginType: { settings: { defaultValue: 'none', encrypt: false, storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true , onSet:(value)=>{if(JSON.parse(value)!=="none"){localStorage.setItem("loginType", JSON.parse(value))}}} },
    oracleURL: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    queryEditor: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    reportScores: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION,defaultValue: false } },
    submissionInfo: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    systemId: { settings: { defaultValue:uuid(),storageType: AutoStorage.STORAGE_TYPE.SESSION } },
    token: { settings: { defaultValue: 'rd2vWW1cG6tOpcVpqurU8vR/m33ZRHbXA0ZAE9k2DbLv8msunrrLWs25R4ejAc6Ur4Kb/hRqQ/K2mA==', encrypt: false, storageType: AutoStorage.STORAGE_TYPE.SESSION, localOnly: true } },
    tutorials: { settings: { storageType: AutoStorage.STORAGE_TYPE.SESSION } },
}, "Samuel Davies")
