package flags

import (
	"reflect"
	"sort"
	"strings"
	"unicode/utf8"
	"unsafe"
)

func (g *Group) lookupByName(name string, ini bool) (*Option, string) {
	name = strings.ToLower(name)

	if ini {
		if ret := g.IniNames[name]; ret != nil {
			return ret, ret.tag.Get("ini-name")
		}

		if ret := g.Names[name]; ret != nil {
			return ret, ret.Field.Name
		}
	}

	if ret := g.LongNames[name]; ret != nil {
		return ret, ret.LongName
	}

	if utf8.RuneCountInString(name) == 1 {
		r, _ := utf8.DecodeRuneInString(name)

		if ret := g.ShortNames[r]; ret != nil {
			data := make([]byte, utf8.RuneLen(ret.ShortName))
			utf8.EncodeRune(data, ret.ShortName)

			return ret, string(data)
		}
	}

	return nil, ""
}

func (g *Group) storeDefaults() {
	for _, option := range g.Options {
		// First. empty out the value
		if len(option.Default) > 0 {
			option.clear()
		}

		for _, d := range option.Default {
			option.Set(&d)
		}

		if !option.Value.CanSet() {
			continue
		}

		option.defaultValue = reflect.ValueOf(option.Value.Interface())
	}
}

func (g *Group) scanStruct(realval reflect.Value, sfield *reflect.StructField) error {
	stype := realval.Type()

	if sfield != nil {
		mtag := newMultiTag(string(sfield.Tag))

		groupName := mtag.Get("group")
		commandName := mtag.Get("command")
		name := mtag.Get("name")
		description := mtag.Get("description")

		iscommand := false

		if len(commandName) != 0 {
			iscommand = true

			if len(name) != 0 {
				groupName = name
			} else if len(commandName) != 0 {
				groupName = commandName
			}
		}

		if len(groupName) != 0 {
			ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr()))
			newGroup := NewGroup(groupName, ptrval.Interface())

			if iscommand {
				newGroup.IsCommand = true
				g.Commands[commandName] = newGroup
			}

			newGroup.LongDescription = description

			g.EmbeddedGroups = append(g.EmbeddedGroups, newGroup)
			return g.Error
		}
	}

	for i := 0; i < stype.NumField(); i++ {
		field := stype.Field(i)

		// PkgName is set only for non-exported fields, which we ignore
		if field.PkgPath != "" {
			continue
		}

		mtag := newMultiTag(string(field.Tag))

		// Skip fields with the no-flag tag
		if mtag.Get("no-flag") != "" {
			continue
		}

		// Dive deep into structs or pointers to structs
		kind := field.Type.Kind()

		if kind == reflect.Struct {
			err := g.scanStruct(realval.Field(i), &field)

			if err != nil {
				return err
			}

		} else if kind == reflect.Ptr &&
			field.Type.Elem().Kind() == reflect.Struct &&
			!realval.Field(i).IsNil() {
			err := g.scanStruct(reflect.Indirect(realval.Field(i)),
				&field)

			if err != nil {
				return err
			}
		}

		longname := mtag.Get("long")
		shortname := mtag.Get("short")

		if longname == "" && shortname == "" {
			continue
		}

		short := rune(0)
		rc := utf8.RuneCountInString(shortname)

		if rc > 1 {
			return ErrShortNameTooLong
		} else if rc == 1 {
			short, _ = utf8.DecodeRuneInString(shortname)
		}

		description := mtag.Get("description")
		def := mtag.GetMany("default")
		optionalValue := mtag.GetMany("optional-value")
		valueName := mtag.Get("value-name")

		optional := (mtag.Get("optional") != "")
		required := (mtag.Get("required") != "")

		option := &Option{
			Description:      description,
			ShortName:        short,
			LongName:         longname,
			Default:          def,
			OptionalArgument: optional,
			OptionalValue:    optionalValue,
			Required:         required,
			Field:            field,
			Value:            realval.Field(i),
			ValueName:        valueName,
			tag:              mtag,
		}

		g.Options = append(g.Options, option)

		if option.ShortName != 0 {
			g.ShortNames[option.ShortName] = option
		}

		if option.LongName != "" {
			g.LongNames[strings.ToLower(option.LongName)] = option
		}

		g.Names[strings.ToLower(field.Name)] = option

		ininame := mtag.Get("ini-name")

		if len(ininame) != 0 {
			g.IniNames[strings.ToLower(ininame)] = option
		}
	}

	return nil
}

func (g *Group) each(index int, cb func(int, *Group)) int {
	cb(index, g)
	index++

	for _, group := range g.EmbeddedGroups {
		group.each(index, cb)
		index++
	}

	return index
}

func (g *Group) eachCommand(cb func(string, *Group)) {
	cmds := make([]string, len(g.Commands))
	i := 0

	for k, _ := range g.Commands {
		cmds[i] = k
	}

	sort.Strings(cmds)

	for _, k := range cmds {
		cb(k, g.Commands[k])
	}
}

func (g *Group) scan() error {
	// Get all the public fields in the data struct
	ptrval := reflect.ValueOf(g.data)

	if ptrval.Type().Kind() != reflect.Ptr {
		panic(ErrNotPointerToStruct)
	}

	stype := ptrval.Type().Elem()

	if stype.Kind() != reflect.Struct {
		panic(ErrNotPointerToStruct)
	}

	realval := reflect.Indirect(ptrval)
	return g.scanStruct(realval, nil)
}
