package yqlib

import (
	"bytes"
	"io"

	"github.com/goccy/go-json"
	yaml "gopkg.in/yaml.v3"
)

type jsonEncoder struct {
	indentString string
	colorise     bool
	UnwrapScalar bool
}

func mapKeysToStrings(node *yaml.Node) {

	if node.Kind == yaml.MappingNode {
		for index, child := range node.Content {
			if index%2 == 0 { // its a map key
				child.Tag = "!!str"
			}
		}
	}

	for _, child := range node.Content {
		mapKeysToStrings(child)
	}
}

func NewJSONEncoder(indent int, colorise bool, unwrapScalar bool) Encoder {
	var indentString = ""

	for index := 0; index < indent; index++ {
		indentString = indentString + " "
	}

	return &jsonEncoder{indentString, colorise, unwrapScalar}
}

func (je *jsonEncoder) CanHandleAliases() bool {
	return false
}

func (je *jsonEncoder) PrintDocumentSeparator(writer io.Writer) error {
	return nil
}

func (je *jsonEncoder) PrintLeadingContent(writer io.Writer, content string) error {
	return nil
}

func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {

	if node.Kind == yaml.ScalarNode && je.UnwrapScalar {
		return writeString(writer, node.Value+"\n")
	}

	destination := writer
	tempBuffer := bytes.NewBuffer(nil)
	if je.colorise {
		destination = tempBuffer
	}

	var encoder = json.NewEncoder(destination)
	encoder.SetEscapeHTML(false) // do not escape html chars e.g. &, <, >
	encoder.SetIndent("", je.indentString)

	var dataBucket orderedMap
	// firstly, convert all map keys to strings
	mapKeysToStrings(node)
	errorDecoding := node.Decode(&dataBucket)
	if errorDecoding != nil {
		return errorDecoding
	}
	err := encoder.Encode(dataBucket)
	if err != nil {
		return err
	}
	if je.colorise {
		return colorizeAndPrint(tempBuffer.Bytes(), writer)
	}
	return nil
}
