package goyaml

// #include "helpers.h"
import "C"

import (
	"reflect"
	"strconv"
	"unsafe"
)

type encoder struct {
	emitter C.yaml_emitter_t
	event   C.yaml_event_t
	out     []byte
	tmp     []byte
	tmph    *reflect.SliceHeader
	flow    bool
}

//export outputHandler
func outputHandler(data unsafe.Pointer, buffer *C.uchar, size C.size_t) C.int {
	e := (*encoder)(data)
	e.tmph.Data = uintptr(unsafe.Pointer(buffer))
	e.tmph.Len = int(size)
	e.tmph.Cap = int(size)
	e.out = append(e.out, e.tmp...)
	return 1
}

func newEncoder() (e *encoder) {
	e = &encoder{}
	e.tmph = (*reflect.SliceHeader)(unsafe.Pointer(&e.tmp))
	if C.yaml_emitter_initialize(&e.emitter) == 0 {
		panic("Failed to initialize YAML emitter")
	}
	C.set_output_handler(&e.emitter)
	C.yaml_stream_start_event_initialize(&e.event, C.YAML_UTF8_ENCODING)
	e.emit()
	C.yaml_document_start_event_initialize(&e.event, nil, nil, nil, 1)
	e.emit()
	return e
}

func (e *encoder) finish() {
	C.yaml_document_end_event_initialize(&e.event, 1)
	e.emit()
	e.emitter.open_ended = 0
	C.yaml_stream_end_event_initialize(&e.event)
	e.emit()
}

func (e *encoder) destroy() {
	C.yaml_emitter_delete(&e.emitter)
}

func (e *encoder) emit() {
	// This will internally delete the e.event value.
	if C.yaml_emitter_emit(&e.emitter, &e.event) == 0 &&
		e.event._type != C.YAML_DOCUMENT_END_EVENT &&
		e.event._type != C.YAML_STREAM_END_EVENT {
		if e.emitter.error == C.YAML_EMITTER_ERROR {
			// XXX TESTME
			panic("YAML emitter error: " + C.GoString(e.emitter.problem))
		} else {
			// XXX TESTME
			panic("Unknown YAML emitter error")
		}
	}
}

func (e *encoder) fail(msg string) {
	if msg == "" {
		if e.emitter.problem != nil {
			msg = C.GoString(e.emitter.problem)
		} else {
			msg = "Unknown problem generating YAML content"
		}
	}
	panic(msg)
}

func (e *encoder) marshal(tag string, in reflect.Value) {
	var value interface{}
	if getter, ok := in.Interface().(Getter); ok {
		tag, value = getter.GetYAML()
		if value == nil {
			e.nilv()
			return
		}
		in = reflect.ValueOf(value)
	}
	switch in.Kind() {
	case reflect.Interface:
		if in.IsNil() {
			e.nilv()
		} else {
			e.marshal(tag, in.Elem())
		}
	case reflect.Map:
		e.mapv(tag, in)
	case reflect.Ptr:
		if in.IsNil() {
			e.nilv()
		} else {
			e.marshal(tag, in.Elem())
		}
	case reflect.Struct:
		e.structv(tag, in)
	case reflect.Slice:
		e.slicev(tag, in)
	case reflect.String:
		e.stringv(tag, in)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		e.intv(tag, in)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		e.uintv(tag, in)
	case reflect.Float32, reflect.Float64:
		e.floatv(tag, in)
	case reflect.Bool:
		e.boolv(tag, in)
	default:
		panic("Can't marshal type yet: " + in.Type().String())
	}
}

func (e *encoder) mapv(tag string, in reflect.Value) {
	e.mappingv(tag, func() {
		for _, k := range in.MapKeys() {
			e.marshal("", k)
			e.marshal("", in.MapIndex(k))
		}
	})
}

func (e *encoder) structv(tag string, in reflect.Value) {
	fields, err := getStructFields(in.Type())
	if err != nil {
		panic(err)
	}
	e.mappingv(tag, func() {
		for i, info := range fields.List {
			value := in.Field(i)
			if info.OmitEmpty && isZero(value) {
				continue
			}
			e.marshal("", reflect.ValueOf(info.Key))
			e.flow = info.Flow
			e.marshal("", value)
		}
	})
}

func (e *encoder) mappingv(tag string, f func()) {
	var ctag *C.yaml_char_t
	var free func()
	cimplicit := C.int(1)
	if tag != "" {
		ctag, free = ystr(tag)
		defer free()
		cimplicit = 0
	}
	cstyle := C.yaml_mapping_style_t(C.YAML_BLOCK_MAPPING_STYLE)
	if e.flow {
		e.flow = false
		cstyle = C.YAML_FLOW_MAPPING_STYLE
	}
	C.yaml_mapping_start_event_initialize(&e.event, nil, ctag, cimplicit,
		cstyle)
	e.emit()
	f()
	C.yaml_mapping_end_event_initialize(&e.event)
	e.emit()
}

func (e *encoder) slicev(tag string, in reflect.Value) {
	var ctag *C.yaml_char_t
	var free func()
	var cimplicit C.int
	if tag != "" {
		ctag, free = ystr(tag)
		defer free()
		cimplicit = 0
	} else {
		cimplicit = 1
	}

	cstyle := C.yaml_sequence_style_t(C.YAML_BLOCK_SEQUENCE_STYLE)
	if e.flow {
		e.flow = false
		cstyle = C.YAML_FLOW_SEQUENCE_STYLE
	}
	C.yaml_sequence_start_event_initialize(&e.event, nil, ctag, cimplicit,
		cstyle)
	e.emit()
	n := in.Len()
	for i := 0; i < n; i++ {
		e.marshal("", in.Index(i))
	}
	C.yaml_sequence_end_event_initialize(&e.event)
	e.emit()
}

func (e *encoder) stringv(tag string, in reflect.Value) {
	var style C.yaml_scalar_style_t
	s := in.String()
	if rtag, _ := resolve("", s); rtag != "!!str" {
		style = C.YAML_DOUBLE_QUOTED_SCALAR_STYLE
	} else {
		style = C.YAML_PLAIN_SCALAR_STYLE
	}
	e.emitScalar(s, "", tag, style)
}

func (e *encoder) boolv(tag string, in reflect.Value) {
	var s string
	if in.Bool() {
		s = "true"
	} else {
		s = "false"
	}
	e.emitScalar(s, "", tag, C.YAML_PLAIN_SCALAR_STYLE)
}

func (e *encoder) intv(tag string, in reflect.Value) {
	s := strconv.Itoa64(in.Int())
	e.emitScalar(s, "", tag, C.YAML_PLAIN_SCALAR_STYLE)
}

func (e *encoder) uintv(tag string, in reflect.Value) {
	s := strconv.Uitoa64(in.Uint())
	e.emitScalar(s, "", tag, C.YAML_PLAIN_SCALAR_STYLE)
}

func (e *encoder) floatv(tag string, in reflect.Value) {
	// FIXME: Handle 64 bits here.
	s := strconv.Ftoa32(float32(in.Float()), 'g', -1)
	switch s {
	case "+Inf":
		s = ".inf"
	case "-Inf":
		s = "-.inf"
	case "NaN":
		s = ".nan"
	}
	e.emitScalar(s, "", tag, C.YAML_PLAIN_SCALAR_STYLE)
}

func (e *encoder) nilv() {
	e.emitScalar("null", "", "", C.YAML_PLAIN_SCALAR_STYLE)
}

func (e *encoder) emitScalar(value, anchor, tag string, style C.yaml_scalar_style_t) {
	var canchor, ctag, cvalue *C.yaml_char_t
	var cimplicit C.int
	var free func()
	if anchor != "" {
		canchor, free = ystr(anchor)
		defer free()
	}
	if tag != "" {
		ctag, free = ystr(tag)
		defer free()
		cimplicit = 0
		style = C.YAML_PLAIN_SCALAR_STYLE
	} else {
		cimplicit = 1
	}
	cvalue, free = ystr(value)
	defer free()
	size := C.int(len(value))
	if C.yaml_scalar_event_initialize(&e.event, canchor, ctag, cvalue, size,
		cimplicit, cimplicit, style) == 0 {
		e.fail("")
	}
	e.emit()
}

func ystr(s string) (ys *C.yaml_char_t, free func()) {
	up := unsafe.Pointer(C.CString(s))
	ys = (*C.yaml_char_t)(up)
	free = func() { C.free(up) }
	return ys, free
}
