// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bind

import (
	"fmt"
	"go/types"
	"log"
	"strings"
)

type ifaceSummary struct {
	iface         *types.Interface
	callable      []*types.Func
	implementable bool
}

func makeIfaceSummary(iface *types.Interface) ifaceSummary {
	summary := ifaceSummary{
		iface:         iface,
		implementable: true,
	}
	methodset := types.NewMethodSet(iface)
	for i := 0; i < methodset.Len(); i++ {
		obj := methodset.At(i).Obj()
		if !obj.Exported() {
			summary.implementable = false
			continue
		}
		m, ok := obj.(*types.Func)
		if !ok {
			log.Panicf("unexpected methodset obj: %s (%T)", obj, obj)
		}
		if !isImplementable(m.Type().(*types.Signature)) {
			summary.implementable = false
		}
		if isCallable(m) {
			summary.callable = append(summary.callable, m)
		}
	}
	return summary
}

func isCallable(t *types.Func) bool {
	// TODO(crawshaw): functions that are not implementable from
	// another language may still be callable (for example, a
	// returned value with an unexported type can be treated as
	// an opaque value by the caller). This restriction could be
	// lifted.
	return isImplementable(t.Type().(*types.Signature))
}

func isImplementable(sig *types.Signature) bool {
	params := sig.Params()
	for i := 0; i < params.Len(); i++ {
		if !isExported(params.At(i).Type()) {
			return false
		}
	}
	res := sig.Results()
	for i := 0; i < res.Len(); i++ {
		if !isExported(res.At(i).Type()) {
			return false
		}
	}
	return true
}

func exportedMethodSet(T types.Type) []*types.Func {
	var methods []*types.Func
	methodset := types.NewMethodSet(T)
	for i := 0; i < methodset.Len(); i++ {
		obj := methodset.At(i).Obj()
		if !obj.Exported() {
			continue
		}
		// Skip methods from the embedded classes, so that
		// only methods that are implemented in Go are included.
		if pref := pkgFirstElem(obj.Pkg()); pref == "Java" || pref == "ObjC" {
			continue
		}
		switch obj := obj.(type) {
		case *types.Func:
			methods = append(methods, obj)
		default:
			log.Panicf("unexpected methodset obj: %s", obj)
		}
	}
	return methods
}

func exportedFields(T *types.Struct) []*types.Var {
	var fields []*types.Var
	for i := 0; i < T.NumFields(); i++ {
		f := T.Field(i)
		if !f.Exported() {
			continue
		}
		fields = append(fields, f)
	}
	return fields
}

func isErrorType(t types.Type) bool {
	return types.Identical(t, types.Universe.Lookup("error").Type())
}

func isExported(t types.Type) bool {
	if isErrorType(t) {
		return true
	}
	switch t := t.(type) {
	case *types.Basic:
		return true
	case *types.Named:
		return t.Obj().Exported()
	case *types.Pointer:
		return isExported(t.Elem())
	default:
		return true
	}
}

func isRefType(t types.Type) bool {
	if isErrorType(t) {
		return false
	}
	switch t := t.(type) {
	case *types.Named:
		switch u := t.Underlying().(type) {
		case *types.Interface:
			return true
		default:
			panic(fmt.Sprintf("unsupported named type: %s / %T", u, u))
		}
	case *types.Pointer:
		return isRefType(t.Elem())
	default:
		return false
	}
}

func isNullableType(t types.Type) bool {
	return types.AssignableTo(types.Typ[types.UntypedNil].Underlying(), t) || t.String() == "string" // string is mapped to NSString*, which is nullable
}

func typePkgFirstElem(t types.Type) string {
	nt, ok := t.(*types.Named)
	if !ok {
		return ""
	}
	return pkgFirstElem(nt.Obj().Pkg())
}

func pkgFirstElem(p *types.Package) string {
	if p == nil {
		return ""
	}
	path := p.Path()
	idx := strings.Index(path, "/")
	if idx == -1 {
		return path
	}
	return path[:idx]
}

func isWrapperType(t types.Type) bool {
	e := typePkgFirstElem(t)
	return e == "Java" || e == "ObjC"
}
