package registry

import (
	"fmt"
	"reflect"
)

// Entry contains a function description params etc
type Entry struct {
	fn          interface{}
	Description *Description
	err         error
}

// NewEntry creates and describes a New Entry
func NewEntry(fn interface{}) *Entry {
	e := &Entry{fn: fn}

	fntyp := reflect.TypeOf(e.fn)
	if fntyp.Kind() != reflect.Func {
		e.err = ErrNotAFunc
		return e
	}
	if fntyp.NumOut() == 0 {
		e.err = ErrOutput
		return e
	}

	fnTyp := reflect.TypeOf(e.fn)
	Inputs := []string{}
	nInputs := fnTyp.NumIn()
	for i := 0; i < nInputs; i++ {
		Inputs = append(Inputs, fmt.Sprint(fnTyp.In(i)))
	}
	Output := fmt.Sprint(fnTyp.Out(0))

	e.Description = &Description{
		Categories: []string{"generic"},
		Inputs:     Inputs,
		Output:     Output,
	}
	return e
}

// Err returns error of the entry if any
func (e *Entry) Err() error {
	return e.err
}

//Categories of the entry
func (e *Entry) Categories(cat ...string) *Entry {
	if e.err != nil {
		return e
	}
	e.Description.Categories = cat

	return e
}
