class Game {
    constructor () {
        this._events = []
        this._filters = []
        this._funcs = {}
        this._config = {}

        this.run = true
    }

    init (canvas) {
        this.canvas = canvas
        this.ctx = this.canvas.getContext('2d')

        this.resize()

        window.addEventListener('resize', ev => this.resize())
    }

    resize () {
        this.rect = this.canvas.getBoundingClientRect()

        this.width = this.rect.width
        this.height = this.rect.height

        this.canvas.width = this.rect.width
        this.canvas.height = this.rect.height

        this.emit('size', [this.width, this.height])
    }

    loop () {
        let lastTime = 0

        const fn = (time) => {
            if (! this.run) return
            requestAnimationFrame (fn)

            // console.time('tick')
            const dt = time - lastTime
            lastTime = time

            this.emit('draw', {
                ctx: this.ctx,
                dt: dt / 1000
            })
            // console.timeEnd('tick')
        }

        fn(new Date)
    }

    on (event, fn, prio = 10) {
        if (! this._events[event]) {
            this._events[event] = []
        }

        this._events[event].push({
            fn,
            prio
        })

        this._events[event].sort((a, b) => +(a.prio > b.prio) || +(a.prio === b.prio) - 1)
    }

    emit (event, data) {
        const events = this._events[event] || []
        events.forEach(ev => ev.fn(data))
    }

    func (name, fn) {
        if (fn) {
            this._funcs[name] = fn
        } else {
            return this._funcs[name]
        }
    }

    config (name, val) {
        if (!name) {
            return this._config
        }

        if (val) {
            this._config[name] = val
        }

        return this._config[name]
    }

    stop () {
        this.run = false
    }
}

export default new Game()
