//
// goyaml - YAML support for the Go language
//
//   https://wiki.ubuntu.com/goyaml
//
// Copyright (c) 2011 Canonical Ltd.
//
// Written by Gustavo Niemeyer <gustavo.niemeyer@canonical.com>
//
package goyaml

import (
	"reflect"
	"runtime"
	"strings"
	"sync"
	"os"
)

func handleErr(err *os.Error) {
	if r := recover(); r != nil {
		if _, ok := r.(runtime.Error); ok {
			panic(r)
		} else if s, ok := r.(string); ok {
			*err = os.ErrorString("YAML error: " + s)
		} else if e, ok := r.(os.Error); ok {
			*err = e
		} else {
			panic(r)
		}
	}
}

// Objects implementing the goyaml.Setter interface will receive the YAML
// tag and value via the SetYAML method during unmarshaling, rather than
// being implicitly assigned by the goyaml machinery.  If setting the value
// works, the method should return true.  If it returns false, the given
// value will be omitted from maps and slices.
type Setter interface {
	SetYAML(tag string, value interface{}) bool
}

// Objects implementing the goyaml.Getter interface will get the GetYAML()
// method called when goyaml is requested to marshal the given value, and
// the result of this method will be marshaled in place of the actual object.
type Getter interface {
	GetYAML() (tag string, value interface{})
}

// Unmarshal decodes the first document found within the in byte slice
// and assigns decoded values into the object pointed by out.
//
// Maps, pointers to structs and ints, etc, may all be used as out values.
// If an internal pointer within a struct is not initialized, goyaml
// will initialize it if necessary for unmarshalling the provided data,
// but the struct provided as out must not be a nil pointer.
// 
// The type of the decoded values and the type of out will be considered,
// and Unmarshal() will do the best possible job to unmarshal values
// appropriately.  It is NOT considered an error, though, to skip values
// because they are not available in the decoded YAML, or if they are not
// compatible with the out value. To ensure something was properly
// unmarshaled use a map or compare against the previous value for the
// field (usually the zero value).
//
// Struct fields are only unmarshalled if they are exported (have an
// upper case first letter), and will be unmarshalled using the field
// name lowercased by default. When custom field names are desired, the
// tag value may be used to tweak the name. Everything before the last
// slash in the field tag will be used as the name. The value following
// the slash is used to tweak the marshalling process (see Marshal).
//
// For example:
//
//     type T struct {
//         F int "a/c"
//         B int
//     }
//     var T t
//     goyaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
// 
func Unmarshal(in []byte, out interface{}) (err os.Error) {
	defer handleErr(&err)
	d := newDecoder()
	p := newParser(in)
	defer p.destroy()
	node := p.parse()
	if node != nil {
		d.unmarshal(node, reflect.NewValue(out))
	}
	return nil
}

// Marshal writes the object provided into a YAML document. The structure
// of the generated document will reflect the structure of the value itself.
// Maps, pointers to structs and ints, etc, may all be used as the in value.
//
// Struct fields are only marshalled if they are exported (have an
// upper case first letter), and will be marshalled using the field
// name lowercased by default. When custom field names are desired, the
// tag value may be used to tweak the name. Everything before the last
// slash in the field tag will be used as the name. The characters
// following the slash are used as flags for the marshalling process,
// with 'c' meaning conditional (only marshal if non-zero), and 'f'
// meaning use flow style (useful for structs, sequences and maps).
//
// For example:
//
//     type T struct {
//         F int "a/c"
//         B int
//     }
//     goyaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
//     goyaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
//
func Marshal(in interface{}) (out []byte, err os.Error) {
	defer handleErr(&err)
	e := newEncoder()
	defer e.destroy()
	e.marshal("", reflect.NewValue(in))
	e.finish()
	out = e.out
	return
}


// --------------------------------------------------------------------------
// Maintain a mapping of keys to structure field indexes

// The code in this section was copied from gobson.

type structFields struct {
	Map  map[string]fieldInfo
	List []fieldInfo
}

type fieldInfo struct {
	Key         string
	Num         int
	Conditional bool
	Flow        bool
}

var fieldMap = make(map[string]*structFields)
var fieldMapMutex sync.RWMutex

func getStructFields(st *reflect.StructType) (*structFields, os.Error) {
	path := st.PkgPath()
	name := st.Name()

	fullName := path + "." + name
	fieldMapMutex.RLock()
	fields, found := fieldMap[fullName]
	fieldMapMutex.RUnlock()
	if found {
		return fields, nil
	}

	n := st.NumField()
	fieldsMap := make(map[string]fieldInfo)
	fieldsList := make([]fieldInfo, n)
	for i := 0; i != n; i++ {
		field := st.Field(i)
		if field.PkgPath != "" {
			continue // Private field
		}

		info := fieldInfo{Num: i}

		if s := strings.LastIndex(field.Tag, "/"); s != -1 {
			for _, c := range field.Tag[s+1:] {
				switch c {
				case int('c'):
					info.Conditional = true
				case int('f'):
					info.Flow = true
				default:
					panic("Unsupported field flag: " + string([]int{c}))
				}
			}
			field.Tag = field.Tag[:s]
		}

		if field.Tag != "" {
			info.Key = field.Tag
		} else {
			info.Key = strings.ToLower(field.Name)
		}

		if _, found = fieldsMap[info.Key]; found {
			msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
			return nil, os.NewError(msg)
		}

		fieldsList[len(fieldsMap)] = info
		fieldsMap[info.Key] = info
	}

	fields = &structFields{fieldsMap, fieldsList[:len(fieldsMap)]}

	if fullName != "." {
		fieldMapMutex.Lock()
		fieldMap[fullName] = fields
		fieldMapMutex.Unlock()
	}

	return fields, nil
}

func isZero(v reflect.Value) bool {
	switch v := v.(type) {
	case *reflect.StringValue:
		return len(v.Get()) == 0
	case *reflect.InterfaceValue:
		return v.IsNil()
	case *reflect.SliceValue:
		return v.Len() == 0
	case *reflect.MapValue:
		return v.Len() == 0
	case *reflect.IntValue:
		return v.Get() == 0
	case *reflect.UintValue:
		return v.Get() == 0
	case *reflect.BoolValue:
		return !v.Get()
	}
	return false
}
