'use strict'

let io = null
let reconnectingText = null
let lastMessage = null
const MIN_WAIT = 100
let wait = MIN_WAIT

function resetWait() {
    wait = MIN_WAIT
}

function incrementWait() {
    const MAX_WAIT = 2000
    if (wait < MAX_WAIT)
        wait *= 1.25
    else
        wait = MAX_WAIT
}

function connect(address) {
    io = new WebSocket(address)
    io.onopen = () => {
        resetWait()
        if (reconnectingText) {
            app.stage.removeChild(reconnectingText)
            reconnectingText = null
        }
    };

    io.onmessage = (msg) => {
        states.push(JSON.parse(msg.data))
    }

    io.onclose = () => {
        if (!reconnectingText && app) {
            reconnectingText = new PIXI.Text('Reconnecting...')
            reconnectingText.anchor.set(0.5)
            reconnectingText.y = 500
            reconnectingText.x = 400
            app.stage.addChild(reconnectingText)
        }
        io = null
        setTimeout(() => {
            incrementWait()
            connect(address);
        }, wait)
    };

    io.onerror = (err) => {
        console.error('Socket encountered error: ', err.message, 'Closing socket')
        io.close()
        io = null
    };
}



function send(data) {
    if (io && io.readyState === 1) {
        console.log('sending data: ', data)
        io.send(data)
    }
}

const Application = PIXI.Application,
    loader = PIXI.loader,
    resources = PIXI.loader.resources,
    Sprite = PIXI.Sprite

const app = new Application(
    1000, 1000, {
        backgroundColor: 0x1099bb,
        autoResize: true,
        antialias: true,
        resolution: 1,
    },
)

const addr = window.location.hostname === 'localhost' ? 'ws://localhost:8081' : 'wss://beta.jnferner.com/socket'
connect(addr)
document.body.appendChild(app.view)

loader
    .add([{
        name: 'dungeonAtlas',
        url: 'assets/dungeon.json'
    }, ])
    .on('progress', loadProgressHandler)
    .load(setup)

app.ticker.add(gameLoop)

document.addEventListener("keydown", (event) => {
    send('keydown:' + event.key)
})
document.addEventListener("keyup", (event) => {
    send('keyup:' + event.key)
})
document.addEventListener("mousemove", (event) => {
    //send('mousemove:' + event.clientX + ' ' + event.clientY)
})

function loadProgressHandler(loader, resource) {
    console.log('loading: ' + resource.name + ' (' + resource.url + ')')
    console.log('progress: ' + loader.progress + '%')
    if (resource.error)
        console.error(resource.error)
}

let blobs = []

function setup() {
    for (let i = 0; i < 1; i++) {
        const blob = new Sprite(resources.dungeonAtlas.textures['blob.png'])
        app.stage.addChild(blob)
        blobs.push(blob)
    }

    for (let obj of app.stage.children)
        initObj(obj)
}

let state = play

function gameLoop(delta) {
    state(delta)
}

let states = []

function play(delta) {
    render(states)
}

function initObj(obj) {
    if (obj.vx === undefined)
        obj.vx = 0
    if (obj.vy === undefined)
        obj.vy = 0
    if (obj.vrotation === undefined)
        obj.vrotation = 0
    obj.anchor.set(0.5)
}

const INTERPOLATION_DELTA = 100

function render(states) {
    const now = timestamp()
    const renderTime = now - INTERPOLATION_DELTA
    const index = getIndexOfRenderState(states, renderTime)
    if (index === null)
        return
    states.splice(0, index)
    let interpolatedState = getInterpolatedState(states[0], states[1], renderTime)
    setWorld(interpolatedState)
}

function getIndexOfRenderState(states, renderTime) {
    let found = null
    for (let i = 0; i < states.length; i++) {
        if (states[i].timestamp >= renderTime) {
            if (i !== 0)
                found = i - 1
            break
        }
    }
    return found
}

function getInterpolatedState(from, to, renderTime) {
    const total = to.timestamp - from.timestamp
    const progress = renderTime - from.timestamp
    if (total === 0 || progress === 0)
        return from
    const fraction = progress / total
    let state = from
    state.vel.x += (to.vel.x - from.vel.x) * fraction
    state.vel.y += (to.vel.y - from.vel.y) * fraction
    state.pos.x += (to.pos.x - from.pos.x) * fraction
    state.pos.y += (to.pos.y - from.pos.y) * fraction
    state.timestamp = renderTime
    return state
}

function timestamp() {
    return new Date().getTime()
}

function setWorld(state) {
    for (let blob of blobs) {
        blob.x = state.pos.x
        blob.y = state.pos.y
    }
}
@@ -17,24 +17,25 @@
 t io = null%0A
+%0A
 let reconnec
@@ -54,31 +54,8 @@
 ull%0A
-let lastMessage = null%0A
 cons
@@ -92,16 +92,33 @@
 N_WAIT%0A%0A
+let states = %5B%5D%0A%0A
 function
@@ -2149,126 +2149,8 @@
 )%0A%7D)
-%0Adocument.addEventListener(%22mousemove%22, (event) =%3E %7B%0A    //send('mousemove:' + event.clientX + ' ' + event.clientY)%0A%7D)
 %0A%0Afu
@@ -2396,22 +2396,16 @@
 let blob
-s = %5B%5D
 %0A%0Afuncti
@@ -2425,52 +2425,8 @@
     
-for (let i = 0; i %3C 1; i++) %7B%0A        const 
 blob
@@ -2484,24 +2484,45 @@
 .png'%5D)%0A    
+blob.anchor.set(0.5)%0A
     app.stag
@@ -2538,103 +2538,10 @@
 d(bl
-ob)%0A        blobs.push(blob)%0A    %7D%0A%0A    for (let obj of app.stage.children)%0A        initObj(
 ob
-j
 )%0A%7D%0A
@@ -2606,33 +2606,16 @@
 lta)%0A%7D%0A%0A
-let states = %5B%5D%0A%0A
 function
@@ -2655,220 +2655,8 @@
 %0A%7D%0A%0A
-function initObj(obj) %7B%0A    if (obj.vx === undefined)%0A        obj.vx = 0%0A    if (obj.vy === undefined)%0A        obj.vy = 0%0A    if (obj.vrotation === undefined)%0A        obj.vrotation = 0%0A    obj.anchor.set(0.5)%0A%7D%0A%0A
 cons
@@ -2726,25 +2726,34 @@
 t now = 
-timestamp
+new Date().getTime
 ()%0A    c
@@ -3861,127 +3861,36 @@
 %0A%7D%0A%0A
-function timestamp() %7B%0A    return new Date().getTime()%0A%7D%0A%0Afunction setWorld(state) %7B%0A    for (let blob of blobs) %7B%0A    
+%0Afunction setWorld(state) %7B%0A
     
@@ -3910,20 +3910,16 @@
 e.pos.x%0A
-    
     blob
@@ -3935,15 +3935,9 @@
 e.pos.y%0A
-    %7D%0A
 %7D

Remove unneeded code