// Copyright 2022 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 go1.19
// +build go1.19

package main

import (
	"fmt"
	"log"
	"strings"
)

var typeNames = make(map[*Type]string)
var genTypes = make(map[*Type]*newType)

func findTypeNames(model Model) {
	for _, s := range model.Structures {
		for _, e := range s.Extends {
			nameType(e, nil) // all references
		}
		for _, m := range s.Mixins {
			nameType(m, nil) // all references
		}
		for _, p := range s.Properties {
			nameType(p.Type, []string{s.Name, p.Name})
		}
	}
	for _, t := range model.Enumerations {
		nameType(t.Type, []string{t.Name})
	}
	for _, t := range model.TypeAliases {
		nameType(t.Type, []string{t.Name})
	}
	for _, r := range model.Requests {
		nameType(r.Params, []string{"Param", r.Method})
		nameType(r.Result, []string{"Result", r.Method})
		nameType(r.RegistrationOptions, []string{"RegOpt", r.Method})
	}
	for _, n := range model.Notifications {
		nameType(n.Params, []string{"Param", n.Method})
		nameType(n.RegistrationOptions, []string{"RegOpt", n.Method})
	}
}

// nameType populates typeNames[t] with the computed name of the type.
// path is the list of enclosing constructs in the JSON model.
func nameType(t *Type, path []string) string {
	if t == nil || typeNames[t] != "" {
		return ""
	}
	switch t.Kind {
	case "base":
		typeNames[t] = t.Name
		return t.Name
	case "reference":
		typeNames[t] = t.Name
		return t.Name
	case "array":
		nm := "[]" + nameType(t.Element, append(path, "Elem"))
		typeNames[t] = nm
		return nm
	case "map":
		key := nameType(t.Key, nil) // never a generated type
		value := nameType(t.Value.(*Type), append(path, "Value"))
		nm := "map[" + key + "]" + value
		typeNames[t] = nm
		return nm
	// generated types
	case "and":
		nm := nameFromPath("And", path)
		typeNames[t] = nm
		for _, it := range t.Items {
			nameType(it, append(path, "Item"))
		}
		genTypes[t] = &newType{
			name:  nm,
			typ:   t,
			kind:  "and",
			items: t.Items,
			line:  t.Line,
		}
		return nm
	case "literal":
		nm := nameFromPath("Lit", path)
		typeNames[t] = nm
		for _, p := range t.Value.(ParseLiteral).Properties {
			nameType(p.Type, append(path, p.Name))
		}
		genTypes[t] = &newType{
			name:       nm,
			typ:        t,
			kind:       "literal",
			properties: t.Value.(ParseLiteral).Properties,
			line:       t.Line,
		}
		return nm
	case "tuple":
		nm := nameFromPath("Tuple", path)
		typeNames[t] = nm
		for _, it := range t.Items {
			nameType(it, append(path, "Item"))
		}
		genTypes[t] = &newType{
			name:  nm,
			typ:   t,
			kind:  "tuple",
			items: t.Items,
			line:  t.Line,
		}
		return nm
	case "or":
		nm := nameFromPath("Or", path)
		typeNames[t] = nm
		for i, it := range t.Items {
			// these names depend on the ordering within the "or" type
			nameType(it, append(path, fmt.Sprintf("Item%d", i)))
		}
		// this code handles an "or" of stringLiterals (_InitializeParams.trace)
		names := make(map[string]int)
		msg := ""
		for _, it := range t.Items {
			if line, ok := names[typeNames[it]]; ok {
				// duplicate component names are bad
				msg += fmt.Sprintf("lines %d %d dup, %s for %s\n", line, it.Line, typeNames[it], nm)
			}
			names[typeNames[it]] = t.Line
		}
		// this code handles an "or" of stringLiterals (_InitializeParams.trace)
		if len(names) == 1 {
			var solekey string
			for k := range names {
				solekey = k // the sole name
			}
			if solekey == "string" { // _InitializeParams.trace
				typeNames[t] = "string"
				return "string"
			}
			// otherwise unexpected
			log.Printf("unexpected: single-case 'or' type has non-string key %s: %s", nm, solekey)
			log.Fatal(msg)
		} else if len(names) == 2 {
			// if one of the names is null, just use the other, rather than generating an "or".
			// This removes about 40 types from the generated code. An entry in goplsStar
			// could be added to handle the null case, if necessary.
			newNm := ""
			sawNull := false
			for k := range names {
				if k == "null" {
					sawNull = true
				} else {
					newNm = k
				}
			}
			if sawNull {
				typeNames[t] = newNm
				return newNm
			}
		}
		genTypes[t] = &newType{
			name:  nm,
			typ:   t,
			kind:  "or",
			items: t.Items,
			line:  t.Line,
		}
		return nm
	case "stringLiteral": // a single type, like 'kind' or 'rename'
		typeNames[t] = "string"
		return "string"
	default:
		log.Fatalf("nameType: %T unexpected, line:%d path:%v", t, t.Line, path)
		panic("unreachable in nameType")
	}
}

func nameFromPath(prefix string, path []string) string {
	nm := prefix + "_" + strings.Join(path, "_")
	// methods have slashes
	nm = strings.ReplaceAll(nm, "/", "_")
	return nm
}
