/**<
    OctaScript interface to changes queue.

    Author:
        q66 <daniel@octaforge.org>

    License:
        See COPYING.txt.
*/

import core.engine.cubescript as cs
import core.events.signal

import core.externals

var needsapply = []

var M = {}

/**
    Specifies the change type, can be GFX, SOUND or SHADERS.
*/
M.change = enum {
    GFX    : 1 << 0,
    SOUND  : 1 << 1,
    SHADERS: 1 << 2
}
var change = M.change

externals::set("change_add", func(desc, ctype) {
    signal::emit(M, "add", ctype, desc)
})

/**
    Adds a change of the given type and description to the queue assuming
    a change of the same description doesn't already exist.
*/
M.add = func(ctype, desc) {
    for i, v in needsapply.each() {
        if v.desc == desc { return }
    }
    needsapply.push({
        ctype: ctype, desc: desc
    })
}

/**
    Clears out changes of the given type. If not given, clears out all.
*/
M.clear = func(ctype) {
    ctype = ctype || (change.GFX | change.SOUND | change.SHADERS)

    needsapply = needsapply.filter(func(v) {
        if (v.ctype & ctype) == 0 {
            return true
        }
        v.ctype = (v.ctype & ~ctype)
        if v.ctype == 0 {
            return false
        }
        return true
    })
}
externals::set("changes_clear", M.clear)

/**
    Applies all queued changes.
*/
M.apply = func() {
    var changetypes = 0
    for i, v in needsapply.each() {
        changetypes |= v.ctype
    }

    if (changetypes & change.GFX) != 0 {
        cs::execute("resetgl")
    } else if (changetypes & change.SHADERS) != 0 {
        cs::execute("resetshaders")
    }
    if (changetypes & change.SOUND) != 0 {
        cs::execute("resetsound")
    }
}

/**
    Returns a table of all queued changes' descriptions.
*/
M.get = func() {
    return needsapply.map(\v -> v.desc)
}

return M
