// package inspect
package main

import (
	. "fmt"
	. "reflect"
	// "log"
)

import "bytes"
import "go/parser"
import "go/ast"
import "go/token"

import "net/http"
import "net/url"
import "html"
import "strconv"

var _ = html.EscapeString
var _ = html.UnescapeString

type any interface{}

func pr(x ...any) {
	for _, e := range x {
		Printf("##  %#v  ", e)
	}
	Println()
}

// The Registry of numbered objects.
func Load() *ast.File {

	fset := token.NewFileSet() // positions are relative to fset

	// Parse the file containing this very example
	// but stop after processing the imports.
	root, err := parser.ParseFile(fset, "a.go", nil, 0 /*parser.Trace | parser.ParseComments */)
	if err != nil {
		panic(err)
	}

	pr("root", root)

	// Print the imports from the file's AST.
	for _, s := range root.Imports {
		Println(s.Path.Value)
		pr(s)
		pr(s.Path)
		pr(s.Path.Value)
	}
	return root
}

type Registry struct {
	next int
	m    map[int]any
}
type Reply struct {
	w http.ResponseWriter
	r *http.Request

	buf      *bytes.Buffer
	registry *Registry

	query url.Values
}

func NewReply(w http.ResponseWriter, r *http.Request, registry *Registry) *Reply {
	z := &Reply{w: w, r: r, buf: bytes.NewBuffer(nil), registry: registry, query: r.URL.Query()}

	return z
}

func NewInspector(root any) *Registry {
	z := new(Registry)
	z.m = make(map[int]any)
	return z
}

func (p *Registry) Register(x any) int {
	z := p.next
	p.next++
	p.m[z] = x
	return z
}
func (p *Registry) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)

	// z := bytes.NewBuffer(nil)
	// z.WriteString("EHLO\r\n")

	reply := NewReply(w, r, p)
	reply.Emit()

	w.Write(reply.buf.Bytes())
}
func (p *Reply) Emit() {
	pr(p.query)
	s := p.query.Get("n")
	n, err := strconv.Atoi(s)
	if err != nil {
		panic("'n' should be a number: " + s)
	}

	obj := p.registry.m[n]
	p.EmitObject(obj)
}
func (p *Reply) Html(s string) {
	p.buf.WriteString(s)
}
func (p *Reply) Ascii(s string) {
	p.buf.WriteString(html.EscapeString(s))
}
func (p *Reply) EmitObject(x any) {
	p.Ascii(Sprintf("%#v", x))
}

func Serve(root *ast.File) {
	http.Handle("/", NewInspector(root))

	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		Fprintf(w, "Hello, %q ;;; %q", html.EscapeString(r.URL.Path), html.EscapeString(Sprintf("%#v", r.URL.Query())))
	})

	panic(http.ListenAndServe(":8080", nil))
}

func main() {

	var x float64 = 3.4
	Println("type:", TypeOf(x))

	var v = ValueOf(x)
	Println("value:", v)
	Println("value:", v.Kind())
	Println("value:", v.Float())

	root := Load()
	Serve(root)
}
