//go:build ignore

package main

import (
	"fmt"
	"go/format"

	"gopkg.in/yaml.v3"

	"gitlab.com/gitlab-org/cli/internal/config"
)

var configLockPath = "config.yaml.lock"

func main() {
	_, root, err := config.ParseConfigFile(configLockPath)
	if err != nil {
		panic(err)
	}

	rootNode := fmt.Sprintf(`
// Code generated by gen/main.go. DO NOT EDIT.
// Check the internal/config/Readme.md on how to add or modify the config stub.

package config

import (
	"gopkg.in/yaml.v3"
)

func rootConfig() *yaml.Node {
	return &yaml.Node{
		Kind: yaml.DocumentNode,
		%s
	}
}
`, parseContent(root.Content))

	rootFmted, err := format.Source([]byte(rootNode))
	if err != nil {
		panic(err)
	}

	err = config.WriteFile("config_stub.go", rootFmted, 0o644)
	if err != nil {
		panic(err)
	}
}

func parseContent(nodes []*yaml.Node) string {
	if len(nodes) == 0 {
		return ""
	}
	var content string

	content += "Content: []*yaml.Node{\n"
	for _, node := range nodes {
		content += "{\n"
		content += parseNode(node)
		content += "},\n"
	}
	content += "},\n"
	return content
}

func parseNode(node *yaml.Node) string {
	var content string
	if node.HeadComment != "" {
		content += fmt.Sprintf("HeadComment: %q,\n", node.HeadComment)
	}

	kind := nodeKindName(node.Kind)
	if kind == "" {
		panic("unknown node kind")
	}

	content += fmt.Sprintf("Kind: %v,\n", kind)

	if node.FootComment != "" {
		content += fmt.Sprintf("FootComment: %q,\n", node.FootComment)
	}

	if node.Anchor != "" {
		content += fmt.Sprintf("Anchor: %q,\n", node.Anchor)
	}

	if node.Alias != nil {
		content += "Alias: &yaml.Node{\n"
		content += parseNode(node.Alias)
		content += "},\n"

		fmt.Print(*node.Alias)
	}

	content += parseContent(node.Content)

	if node.Value != "" || len(node.Content) == 0 {
		content += fmt.Sprintf("Value: %q,\n", node.Value)
	}

	return content
}

const (
	DocumentNode yaml.Kind = 1 << iota
	SequenceNode
	MappingNode
	ScalarNode
	AliasNode
)

func nodeKindName(kind yaml.Kind) string {
	switch kind {
	case DocumentNode:
		return "yaml.DocumentNode"
	case SequenceNode:
		return "yaml.SequenceNode"
	case MappingNode:
		return "yaml.MappingNode"
	case ScalarNode:
		return "yaml.ScalarNode"
	case AliasNode:
		return "yaml.AliasNode"
	default:
		return ""
	}
}
