// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build js && wasm

package runtime

import (
	"internal/runtime/sys"
	_ "unsafe" // for go:linkname
)

// js/wasm has no support for threads yet. There is no preemption.

const (
	mutex_unlocked = 0
	mutex_locked   = 1

	note_cleared = 0
	note_woken   = 1
	note_timeout = 2

	active_spin     = 4
	active_spin_cnt = 30
	passive_spin    = 1
)

type mWaitList struct{}

func lockVerifyMSize() {}

func mutexContended(l *mutex) bool {
	return false
}

func lock(l *mutex) {
	lockWithRank(l, getLockRank(l))
}

func lock2(l *mutex) {
	if l.key == mutex_locked {
		// js/wasm is single-threaded so we should never
		// observe this.
		throw("self deadlock")
	}
	gp := getg()
	if gp.m.locks < 0 {
		throw("lock count")
	}
	gp.m.locks++
	l.key = mutex_locked
}

func unlock(l *mutex) {
	unlockWithRank(l)
}

func unlock2(l *mutex) {
	if l.key == mutex_unlocked {
		throw("unlock of unlocked lock")
	}
	gp := getg()
	gp.m.locks--
	if gp.m.locks < 0 {
		throw("lock count")
	}
	l.key = mutex_unlocked
}

// One-time notifications.

// Linked list of notes with a deadline.
var allDeadlineNotes *note

func noteclear(n *note) {
	n.status = note_cleared
}

func notewakeup(n *note) {
	if n.status == note_woken {
		throw("notewakeup - double wakeup")
	}
	cleared := n.status == note_cleared
	n.status = note_woken
	if cleared {
		goready(n.gp, 1)
	}
}

func notesleep(n *note) {
	throw("notesleep not supported by js")
}

func notetsleep(n *note, ns int64) bool {
	throw("notetsleep not supported by js")
	return false
}

// same as runtime·notetsleep, but called on user g (not g0)
func notetsleepg(n *note, ns int64) bool {
	gp := getg()
	if gp == gp.m.g0 {
		throw("notetsleepg on g0")
	}

	if ns >= 0 {
		deadline := nanotime() + ns
		delay := ns/1000000 + 1 // round up
		if delay > 1<<31-1 {
			delay = 1<<31 - 1 // cap to max int32
		}

		id := scheduleTimeoutEvent(delay)

		n.gp = gp
		n.deadline = deadline
		if allDeadlineNotes != nil {
			allDeadlineNotes.allprev = n
		}
		n.allnext = allDeadlineNotes
		allDeadlineNotes = n

		gopark(nil, nil, waitReasonSleep, traceBlockSleep, 1)

		clearTimeoutEvent(id) // note might have woken early, clear timeout

		n.gp = nil
		n.deadline = 0
		if n.allprev != nil {
			n.allprev.allnext = n.allnext
		}
		if allDeadlineNotes == n {
			allDeadlineNotes = n.allnext
		}
		n.allprev = nil
		n.allnext = nil

		return n.status == note_woken
	}

	for n.status != note_woken {
		n.gp = gp

		gopark(nil, nil, waitReasonZero, traceBlockGeneric, 1)

		n.gp = nil
	}
	return true
}

// checkTimeouts resumes goroutines that are waiting on a note which has reached its deadline.
func checkTimeouts() {
	now := nanotime()
	for n := allDeadlineNotes; n != nil; n = n.allnext {
		if n.status == note_cleared && n.deadline != 0 && now >= n.deadline {
			n.status = note_timeout
			goready(n.gp, 1)
		}
	}
}

// events is a stack of calls from JavaScript into Go.
var events []*event

type event struct {
	// g was the active goroutine when the call from JavaScript occurred.
	// It needs to be active when returning to JavaScript.
	gp *g
	// returned reports whether the event handler has returned.
	// When all goroutines are idle and the event handler has returned,
	// then g gets resumed and returns the execution to JavaScript.
	returned bool
}

type timeoutEvent struct {
	id int32
	// The time when this timeout will be triggered.
	time int64
}

// diff calculates the difference of the event's trigger time and x.
func (e *timeoutEvent) diff(x int64) int64 {
	if e == nil {
		return 0
	}

	diff := x - idleTimeout.time
	if diff < 0 {
		diff = -diff
	}
	return diff
}

// clear cancels this timeout event.
func (e *timeoutEvent) clear() {
	if e == nil {
		return
	}

	clearTimeoutEvent(e.id)
}

// The timeout event started by beforeIdle.
var idleTimeout *timeoutEvent

// beforeIdle gets called by the scheduler if no goroutine is awake.
// If we are not already handling an event, then we pause for an async event.
// If an event handler returned, we resume it and it will pause the execution.
// beforeIdle either returns the specific goroutine to schedule next or
// indicates with otherReady that some goroutine became ready.
// TODO(drchase): need to understand if write barriers are really okay in this context.
//
//go:yeswritebarrierrec
func beforeIdle(now, pollUntil int64) (gp *g, otherReady bool) {
	delay := int64(-1)
	if pollUntil != 0 {
		// round up to prevent setTimeout being called early
		delay = (pollUntil-now-1)/1e6 + 1
		if delay > 1e9 {
			// An arbitrary cap on how long to wait for a timer.
			// 1e9 ms == ~11.5 days.
			delay = 1e9
		}
	}

	if delay > 0 && (idleTimeout == nil || idleTimeout.diff(pollUntil) > 1e6) {
		// If the difference is larger than 1 ms, we should reschedule the timeout.
		idleTimeout.clear()

		idleTimeout = &timeoutEvent{
			id:   scheduleTimeoutEvent(delay),
			time: pollUntil,
		}
	}

	if len(events) == 0 {
		// TODO: this is the line that requires the yeswritebarrierrec
		go handleAsyncEvent()
		return nil, true
	}

	e := events[len(events)-1]
	if e.returned {
		return e.gp, false
	}
	return nil, false
}

var idleStart int64

func handleAsyncEvent() {
	idleStart = nanotime()
	pause(sys.GetCallerSP() - 16)
}

// clearIdleTimeout clears our record of the timeout started by beforeIdle.
func clearIdleTimeout() {
	idleTimeout.clear()
	idleTimeout = nil
}

// scheduleTimeoutEvent tells the WebAssembly environment to trigger an event after ms milliseconds.
// It returns a timer id that can be used with clearTimeoutEvent.
//
//go:wasmimport gojs runtime.scheduleTimeoutEvent
func scheduleTimeoutEvent(ms int64) int32

// clearTimeoutEvent clears a timeout event scheduled by scheduleTimeoutEvent.
//
//go:wasmimport gojs runtime.clearTimeoutEvent
func clearTimeoutEvent(id int32)

// handleEvent gets invoked on a call from JavaScript into Go. It calls the event handler of the syscall/js package
// and then parks the handler goroutine to allow other goroutines to run before giving execution back to JavaScript.
// When no other goroutine is awake any more, beforeIdle resumes the handler goroutine. Now that the same goroutine
// is running as was running when the call came in from JavaScript, execution can be safely passed back to JavaScript.
func handleEvent() {
	sched.idleTime.Add(nanotime() - idleStart)

	e := &event{
		gp:       getg(),
		returned: false,
	}
	events = append(events, e)

	if !eventHandler() {
		// If we did not handle a window event, the idle timeout was triggered, so we can clear it.
		clearIdleTimeout()
	}

	// wait until all goroutines are idle
	e.returned = true
	gopark(nil, nil, waitReasonZero, traceBlockGeneric, 1)

	events[len(events)-1] = nil
	events = events[:len(events)-1]

	// return execution to JavaScript
	idleStart = nanotime()
	pause(sys.GetCallerSP() - 16)
}

// eventHandler retrieves and executes handlers for pending JavaScript events.
// It returns true if an event was handled.
var eventHandler func() bool

//go:linkname setEventHandler syscall/js.setEventHandler
func setEventHandler(fn func() bool) {
	eventHandler = fn
}
