package main

import (
	"context"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"time"
	"zyel.example/workerlab/engine"
)

func main() {
	mux := http.NewServeMux()
	gate := make(chan struct{}, 1)
	mux.HandleFunc("POST /api/run", func(w http.ResponseWriter, r *http.Request) {
		select {
		case gate <- struct{}{}:
			defer func() { <-gate }()
		default:
			http.Error(w, "An experiment is already running.", http.StatusTooManyRequests)
			return
		}
		r.Body = http.MaxBytesReader(w, r.Body, 2048)
		defer r.Body.Close()
		var config engine.Config
		decoder := json.NewDecoder(r.Body)
		decoder.DisallowUnknownFields()
		if err := decoder.Decode(&config); err != nil {
			http.Error(w, "Invalid configuration", 400)
			return
		}
		if err := decoder.Decode(&struct{}{}); err != io.EOF {
			http.Error(w, "Send exactly one JSON configuration", 400)
			return
		}
		ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
		defer cancel()
		result, err := engine.Run(ctx, config)
		if err != nil {
			http.Error(w, err.Error(), 400)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Cache-Control", "no-store")
		json.NewEncoder(w).Encode(result)
	})
	server := &http.Server{Addr: "127.0.0.1:4188", Handler: mux, ReadHeaderTimeout: 3 * time.Second, ReadTimeout: 5 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 15 * time.Second}
	log.Print("Synthetic worker lab: http://127.0.0.1:4188/api/run (POST)")
	log.Fatal(server.ListenAndServe())
}
