// excel replicates values and functions from Microsoft Excel package excel

import (

"fmt"
"strconv"

)

// cachedValue wraps the different possible Excel Values // // Later, we may have one for each Excel type // which is why we use wrappers. type cachedValue struct {

// v is the cached value, in this case of any type
v interface{}
// c is whether it is cached
c bool

}

func (c *cachedValue) isCached() bool {

return c.c

}

func (c *cachedValue) set(v interface{}) {

c.v = v
c.c = true

}

// get returns the cached value. If the cached // value is an Excel Error that is returned as // the second argument. If the item isn't cached // then will return a NotCachedError. func (c *cachedValue) get() (interface{}, error) {

if !c.c {
        return nil, notCachedError{}
}
if err, ok := c.v.(error); ok {
        return nil, err
}
return c.v, nil

}

type notCachedError struct{}

func (e notCachedError) Error() string {

return "Get() called but nothing cached"

}

// Blank is an empty Excel cell. type Blank struct{}

// The Excel #VALUE! error type ValueError struct {

value interface{}
cast  string

}

// The Excel #NAME? error type NameError struct{}

// The Excel #DIV/0! error type Div0Error struct{}

// The Excel #REF! error type RefError struct{}

// The Excel #N/A error type NAError struct{}

// The Excel #NUM! error type NumError struct{}

func (e ValueError) Error() string {

return fmt.Sprintf("#VALUE!: could not convert %v to %v", e.value, e.cast)

}

func (e NameError) Error() string {

return "#NAME?"

}

func (e Div0Error) Error() string {

return "#DIV/0!"

}

func (e RefError) Error() string {

return "#REF!"

}

func (e NAError) Error() string {

return "#N/A"

}

func (e NumError) Error() string {

return "#DIV/0!"

}

func excel_if(c interface{}, t, f func() interface{}) interface{} {

b, err := boolean(c)
if err != nil {
        return err
}
if b {
        if t == nil {
                return true
        } else {
                return t()
        }
} else {
        if f == nil {
                return false
        } else {
                return f()
        }
}

}

func add(a, b interface{}) interface{} {

n1, err := number(a)
if err != nil {
        return err
}
n2, err := number(b)
if err != nil {
        return err
}
return n1 + n2

}

func number(a interface{}) (float64, error) {

switch a := a.(type) {
case Blank:
        return 0, nil
case float64:
        return a, nil
case bool:
        if a {
                return 1, nil
        } else {
                return 0, nil
        }
case error:
        return 0, a
case string:
        i, err := strconv.ParseFloat(a, 64)
        if err != nil {
                return 0, ValueError{a, "float64"}
        }
        return i, nil
default:
        return 0, ValueError{a, "float64"}
}

}

func boolean(a interface{}) (bool, error) {

switch a := a.(type) {
case Blank:
        return false, nil
case float64:
        if a == 0 {
                return false, nil
        } else {
                return true, nil
        }
case bool:
        return a, nil
case error:
        return false, a
default:
        return false, ValueError{a, "bool"}
}

}