//import { preloadFonts } from './preloadFonts.js'
function preloadFonts() {	// https://stackoverflow.com/questions/53808106/chrome-offscreencanvas-custom-fonts
	const fonts = [
		{name: 'Syncopate', url: 'url(../css/Syncopate.woff2)'},
	]
	fonts.forEach(f=>{
		const fF = new FontFace(f.name, f.url)
		if (self.fonts) {
			self.fonts.add(fF)
			console.log('fonts added to self')
		} else {
			document.fonts.add(fF)
			console.log('fonts added to document')
		}
		fF.load()	// load the font
	})
}
preloadFonts()
//import { getRandomInt } from './getRandomInt.js'
function getRandomInt(min, max) { // min/max incl.
	//console.log('getRandomInt',min, max)
	let array
	if (max <= 255) array = new Uint8Array(1024)
	if (max > 255 && max <= 65535) array = new Uint16Array(512)
	if (max > 65535) array = new Uint32Array(256)
	self.crypto.getRandomValues(array)
	// find first in min/max range
	for (const num of array) {
		if (num>=min && num<=max) return num
	}
	console.log('another round!')
	return getRandomInt(min, max)	// oops still here, go another round
}


let ctx, w = 4096, h = 2160,	// hint: titlespawnObj needs this in advance
mode = '',
game = {
	actPlayer: getRandomInt(0,1),
	lastDice: false,
	transit: -1,	// 0 = player1
	player: [
		{a:'🤖', color: 'yellow', rolled:[], fi: 0, go: 0,
			fields: [{x:682,y:994},{x:780,y:851},{x:783,y:763},{x:781,y:688},{x:782,y:609},{x:689,y:607},{x:595,y:609},{x:502,y:609},{x:407,y:604},{x:313,y:602},{x:218,y:605},{x:125,y:604},{x:29,y:608},{x:27,y:498},{x:29,y:404},{x:124,y:399},{x:217,y:400},{x:313,y:399},{x:407,y:400},{x:503,y:405},{x:596,y:400},{x:691,y:403},{x:784,y:403},{x:783,y:296},{x:782,y:201},{x:690,y:202},{x:594,y:202},{x:506,y:203},{x:406,y:201},{x:312,y:201},{x:216,y:201},{x:126,y:201},{x:29,y:199},{x:29,y:102},{x:29,y:19},{x:125,y:17},{x:214,y:18},{x:307,y:18},{x:403,y:18},{x:500,y:17},{x:591,y:18},{x:672,y:17},{x:782,y:37}],
			objs: [],
			collected: [],
		},
		{a:'🤡', color: 'red', rolled:[], fi: 0, go: 0,
			fields: [{x:1226,y:1000},{x:1119,y:848},{x:1119,y:767},{x:1119,y:689},{x:1119,y:609},{x:1207,y:608},{x:1298,y:609},{x:1386,y:609},{x:1475,y:607},{x:1563,y:608},{x:1656,y:608},{x:1747,y:605},{x:1837,y:607},{x:1840,y:501},{x:1837,y:396},{x:1747,y:398},{x:1657,y:399},{x:1564,y:395},{x:1474,y:396},{x:1386,y:395},{x:1297,y:396},{x:1207,y:394},{x:1119,y:397},{x:1119,y:295},{x:1118,y:198},{x:1211,y:200},{x:1297,y:197},{x:1386,y:200},{x:1474,y:198},{x:1562,y:198},{x:1654,y:199},{x:1746,y:200},{x:1838,y:198},{x:1839,y:103},{x:1837,y:20},{x:1749,y:20},{x:1654,y:20},{x:1568,y:19},{x:1475,y:20},{x:1386,y:19},{x:1299,y:20},{x:1207,y:19},{x:1095,y:39}],
			objs: [],
			collected: [],
		},
	],
},
img = {}	// imageData
let x = 3840/2, y=2160/2
let demoArr = [],
startTime = 0

onmessage = function (e) {
	console.log(e.data)
	// most used message on top, and the only one for this game
	if (e.data.action == 'dice') {
		dice()
		return
	}
	if (e.data.title) {
		mode = 'title'
		return
	}
	if (e.data.reset) {
		resetAll()
		return
	}
	if (e.data.play) {
		mode = 'game'
		startTime = performance.now()
		return
	}
	if (e.data.move) {
		const d = (e.data.shift) ? 10 : 1
		if (e.data.move == 'u') y -= d
		if (e.data.move == 'd') y += d
		if (e.data.move == 'l') x -= d
		if (e.data.move == 'r') x += d
		console.log('Pos:',x,y)
		return
	}
	if (e.data.store) {
		demoArr.push({x:x,y:y})
		console.log('arr:',JSON.stringify(demoArr))
		return
	}

	if (e.data.canvas) {	// 1st init = transfer of offscreen canvas
		const canv = e.data.canvas
		ctx = canv.getContext('2d', {
			alpha: false,
			//colorSpace: 'display-p3',			// default='srgb' todo check what happens without
			//colorType: 'float16',				// default='unorm8'
			desynchronized: true,
			willReadFrequently: false,
		})
		w = canv.width
		h = canv.height
		requestAnimationFrame(renderLoop)

		console.log('renderLoop started')
		return
	}
	console.error('Unknown message:', e.data)	// still here ?
}

let lastRender = 0
function renderLoop(now) {
	ctx.clearRect(0, 0, w, h)
	if (mode == 'title') drawTitle(now)
	if (mode == 'game' || mode == 'win') drawBoard(now)

	lastRender = now
	requestAnimationFrame(renderLoop)
}

function dice() {
	console.log('dice',mode,game.transit)
	if (mode != 'game') return		// not playing yet
	if (game.transit > -1) return	// not yet, other player is still moving
	const r = getRandomInt(0,5)
	game.lastDice = ['⚀','⚁','⚂','⚃','⚄','⚅'][r]
	console.log('you rolled: '+game.lastDice+' = '+(r+1))
	postMessage({status:'dice'})
	game.player[game.actPlayer].rolled.push(game.lastDice)
	game.player[game.actPlayer].go = game.player[game.actPlayer].fi + (r+1)
	// put game is in transit mode and player moves from "go" to "fi"
	game.transit = game.actPlayer
	setTimeout(()=>{ transit() },500)	// wait a bit (till dice sound is finished)

	function transit() {
		const tPlayer = game.player[game.transit]
		if (tPlayer.go > tPlayer.fi) { // forward or backward
			if (tPlayer.go > ++tPlayer.fi) { // end not reached, continue transit
				if (stageCheck()) return

				setTimeout(()=>{ transit() }, 500)
				return
			}
		} else {
			if (tPlayer.go < --tPlayer.fi) { // end not reached, continue transit

				setTimeout(()=>{ transit() }, 500)
				return
			}
		}
	
		// check collision
		let coll = false
		for (let i = 0, o = tPlayer.objs; i < o.length; i++) {
			if (o[i].fi == tPlayer.fi) {
				const el = o[i].o
				o.splice(i,1)
				tPlayer.collected.push( el )
				coll = true
				console.log('collected.. tunnel.. start')
				if (el == '🌭') {
					console.log('hotdog')
					tPlayer.go += 3
					setTimeout(()=>{ transit() }, 500)
					return
				}
				if (el == '🍸') {
					console.log('martini')
					tPlayer.go = Math.max(0,tPlayer.go-4)
					setTimeout(()=>{ transit() }, 500)
					return
				}
				if (el == '🍺') {
					setTimeout(()=>{
						console.log('beer')
						postMessage({ status: 'tunnel' })
						tPlayer.go = 0
						tPlayer.fi = 0
					},500)
				}
			}
		}

		if (stageCheck()) return

		game.actPlayer = (game.actPlayer+1) % 2
		console.log(game.actPlayer)

		game.transit = -1

		function stageCheck() {
			if (tPlayer.fi >= tPlayer.fields.length-1) {
				postMessage({ status: 'win', player: game.transit })
				mode = 'win'
				game.transit = -1
				setTimeout(()=>{ resetAll()	},5000)
				return true
			}
			return false
		}
	}
	game.lastDice = false
}

function resetAll() {
	for (let i = 0; i < game.player.length; i++) {
		game.player[i].fi = 0
		game.player[i].go = 0
		game.player[i].o = []
		game.player[i].rolled = []
		game.player[i].collected = []
	}
	game.actPlayer = getRandomInt(0,1)
	spawnObjects()
	console.log('game objects reset')

}

spawnObjects()
function spawnObjects() {
	const objs = [
		'🍺','🍺','🍺','🍺',//'🍺',
		'🍸','🍸',//'🍸',
		'🌭','🌭','🌭',//'🌭',
	]
	let o = {o0: [...objs], o1: [...objs]}
	secureShuffleArray(o.o0)
	secureShuffleArray(o.o1)
	console.log(o)

	// spread
	for (let p = 0; p < game.player.length; p++) {	// all players
		game.player[p].objs = []
		for (let i = 2; i < 42; i++) {
			if (o['o'+p].length == 0) continue
			const chance = o['o'+p].length / (42-i) * 100
			const r = getRandomInt(0,100)
			if (r < chance) {
				game.player[p].objs.push( {fi: i, o:o['o'+p].pop()} )
				//console.log('spawn at ',p,i)
			}
			//console.log('chance: '+chance, r)
		}
		//console.log(o.o0, o.o1)
	}
	//console.log(game)

	
	function secureShuffleArray(array) {	// https://stackoverflow.com/questions/49003363/cryptographically-secure-array-shuffle
		for (let i = array.length - 1; i > 0; i--) {
			const j = getRandomInt(0, i)
			const temp = array[i]
			array[i] = array[j]
			array[j] = temp
		}
	}
}

function drawTitle(now){
	const delta = Math.min(300,(now - lastRender))
	//console.log(delta)
	// draw object
	for (let i = 0; i < titleObjs.length-1; i++) {
		const o = titleObjs[i]
		o.y -= o.ys * delta / 33	// yes it was designed on 30 fps
		if (o.y < -300) updateTitleObject(i)
		const w = o.wm * Math.sin((now+o.ws)/o.wd)
		ctx.drawImage(img[o.imgId], 0, 0, img[o.imgId].width, img[o.imgId].height, o.x+w, o.y, img[o.imgId].width, img[o.imgId].height)
		//if (i == 0) console.log(o)
	}

	ctx.font = 'bold 300px Syncopate'
	writeText('Tunnel Love',5/32*h)

	ctx.strokeStyle = '#fff'
	ctx.lineWidth = 10
	ctx.font = 'bold 150px Syncopate'
	writeButton('Play', 9/32*h)
	writeButton('Greetings', 13/32*h)
	writeButton('Credits', 17/32*h)
	writeButton('Exit', 21/32*h)

	function writeButton(txt, y) {
		const tDim = ctx.measureText(txt)
		const x = (w-tDim.width)/2
		ctx.fillStyle = '#000a'
		const p = 20, r = 10
		ctx.beginPath()
		ctx.roundRect(x-p, y-tDim.fontBoundingBoxAscent, tDim.width+2*p, tDim.fontBoundingBoxAscent+2*p, r)
		ctx.fill()
		ctx.stroke()
		writeText(txt,y)
	}
	function writeText(txt,y) {
		const tDim = ctx.measureText(txt)
		const x = (w-tDim.width)/2
		ctx.fillStyle = '#fff'
		ctx.fillText(txt,x,y)
	}
}

function drawBoard(now) {
	const wiggle = Math.sin(now/700)
	const wiggleX = Math.cos(now/700)
	const wiggleFast = Math.sin(now/100)

	ctx.drawImage(img.stage, 0, 0, img.stage.width, img.stage.height, 0, 0, w, h)

	ctx.font = '100px sans-serif'
	/*
	for (let i = 1, f = game.player[0].fields; i < f.length-1; i++) {
		ctx.fillText('🍺', f[i].x-3+5*wiggle, f[i].y+42)
	}
	for (let i = 1, f = game.player[1].fields; i < f.length-1; i++) {
		ctx.fillText('🌭', f[i].x-3+5*wiggle, f[i].y+42)
	}
	*/
	for (let p = 0; p < game.player.length; p++) {
		for (let i = 0, o = game.player[p].objs, f = game.player[p].fields; i < o.length; i++) {
			ctx.fillText(o[i].o, f[o[i].fi].x*2-3+6*wiggle, f[o[i].fi].y*2+84)
		}
	}

	const f1 = game.player[0].fields[ Math.min(game.player[0].fields.length-1, game.player[0].fi)]
	ctx.drawImage(img.pl1, 0, 0, img.pl1.width, img.pl1.height, f1.x*2-10*wiggleFast, f1.y*2-10*wiggleFast, 100+20*wiggleFast, 100+10*wiggleFast)

	const f2 = game.player[1].fields[ Math.min(game.player[1].fields.length-1, game.player[1].fi)]
	ctx.drawImage(img.pl2, 0, 0, img.pl2.width, img.pl2.height, f2.x*2-10*wiggleFast, f2.y*2-10*wiggleFast, 100+20*wiggleFast, 100+10*wiggleFast)

	ctx.font = '450px sans-serif'
	ctx.fillStyle = game.player[0].color
	//ctx.fillText(game.player[0].rolled.slice(-6).join(''), 20, 23/24*h)
	ctx.fillText(game.player[0].rolled.slice(-1), 5/32*w, 47/48*h)
	ctx.fillStyle = game.player[1].color
	//ctx.fillText(game.player[1].rolled.slice(-6).join(''), 97/128*w, 23/24*h)
	ctx.fillText(game.player[1].rolled.slice(-1), 25/32*w, 47/48*h)

	ctx.font = '200px sans-serif'
	ctx.fillText('🎲', game.actPlayer ? 17/32*w : 13/32*w, 23/24*h)	// whoms turn

	ctx.font = '60px sans-serif'
	ctx.fillText(game.player[1].collected.join(''), 10/16*w, 4/5*h)
	ctx.fillText(game.player[0].collected.join(''), 20, 4/5*h)

	// goal
	ctx.font = '120px sans-serif'
	ctx.fillText('🏆', 16/32*w-50+120*wiggleX, 2/24*h-30*wiggle)

	// start helpers
	if (game.player[0].rolled.length == 0
		&& game.player[1].rolled.length == 0
		&& mode == 'game'
	) {
		ctx.font = (60+5*wiggle)+'px sans-serif'
		ctx.fillStyle = '#0ff'
		ctx.fillText('Reach the stage', 29/64*w-30*wiggle, 9/48*h)
		ctx.fillText('🍺 back to start', 14/32*w-30*wiggle, 11/24*h)
		ctx.fillText('🍸 4 fields back', 14/32*w-30*wiggle, 12/24*h)
		ctx.fillText('🌭 3 fields forward', 14/32*w-30*wiggle, 13/24*h)
		ctx.fillText('🎲 shows who\'s next', 14/32*w-30*wiggle, 21/24*h)
	}

}

function nextPart() {
	partStart = performance.now() // or audioTime
	console.log('nextPart', partStart)
	postMessage({ part: ++main })
	return
}

postMessage({ status: 'loading resources' })
console.time('load resources')
const imgs = [
	'stage','pl1','pl2',	// those are for the game
	// the rest is for the title page
	// normally i prefer a spritesheet for that to reduce resource load count
	// but i'm in a hurry and load a video meanwhile, who cares
	'icons/01_Atari_1040STf',
	'icons/Amiga_Hacken_Spielfigur',
	'icons/Atari_Schriftzug',
	'icons/dec2',
	'icons/NMAH-RWS2014-02503',
	'icons/2600',
	'icons/amiga-Monitor',
	'icons/Atari_Spielfeld',
	'icons/dec',
	'icons/PET',
	'icons/300px-cpc664',
	'icons/Amiga_Schriftzug',
	'icons/Atari_Streifen_weiß',
	'icons/digital_vt100-7349',
	'icons/Spielfigur_Amigahacken',
	'icons/Amiga500_system1',
	'icons/amstrad-cpc-464-turned-on',
	'icons/CBM3008_01_mod02_res',
	'icons/EC1835_C_cut',
	'icons/Spielfigur_Ataristreifen',
	'icons/Amiga_Ball_Brettsymbol',
	'icons/Atari_LynxI',
	'icons/Commodore-PET-2001-05',
	'icons/GB',
	'icons/Vectrex'
]
let imgsToLoad = imgs.length
imgs.forEach(id=>{
	fetch('../gfx/'+id+'.webp')
	.then(r=>r.blob())
	.then(b=>createImageBitmap(b))
	.then(bmp=>img[id]=bmp)
	.finally(()=>checkAllImgsLoaded())
	.catch(e=>console.error(e))
})
function checkAllImgsLoaded() {
	if (--imgsToLoad <= 0) {
		console.timeEnd('load resources')
		postMessage({ status: 'resources loaded' })
	}
}
/*
async function loadImage(id){
	const res = await fetch('../gfx/'+id+'.png')
	const blob = await res.blob()
	const bmp = await createImageBitmap(blob)
	img[id] = bmp
	//bmp.close()
}
postMessage({ status: 'loading resources' })

async function preloadImages() {
	await loadImage('stage')
	await loadImage('pl1')
	await loadImage('pl2')
	console.timeEnd('load resources')
	postMessage({ status: 'resources loaded' })
}
console.time('load resources')
preloadImages()
*/



const titleObjs = []
for (let i = 3; i < imgs.length-1; i++) spawnTitleObject(imgs[i])
console.log(titleObjs)

function updateTitleObject(i) {
	titleObjs[i].x =  getRandomInt(w/32,27/32*w)// x pos
	titleObjs[i].y = h+getRandomInt(200,1000)	// start out of screen
	titleObjs[i].ys = getRandomInt(1, 5)		// y speed
	titleObjs[i].ws = getRandomInt(0,1000)		// wiggleStart
	titleObjs[i].wd = getRandomInt(500, 1500)	// wiggleDivisor
	titleObjs[i].wm = getRandomInt(10, 100)		// wiggleMuliplier
}
function spawnTitleObject(id) {
	titleObjs.push({
		imgId: id,	// id of obj
		x: getRandomInt(w/32,27/32*w),	// x pos
		y: h+getRandomInt(200,1000),	// start out of screen
		ys: getRandomInt(1, 5),			// y speed
		ws: getRandomInt(0,1000),		// wiggleStart
		wd: getRandomInt(500, 1500),	// wiggleDivisor
		wm: getRandomInt(10, 100),		// wiggleMuliplier
	})
}