// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package tools

import (
	"fmt"
	"go/token"

	"github.com/dave/dst"
	"github.com/dave/dst/decorator"
)

const interfaceName = "interface{}"
const OtherPackageRefPrefix = "swref_"
const parameterAppender = ", "

type ParameterInfo struct {
	Name     string
	Type     dst.Expr
	TypeName string
}

type PackagedParameterInfo struct {
	ParameterInfo
	PackageName string
}

type FieldListType int

const (
	FieldListTypeParam FieldListType = iota
	FieldListTypeResult
	FieldListTypeRecv
)

func (f FieldListType) String() string {
	switch f {
	case FieldListTypeRecv:
		return "recv"
	case FieldListTypeParam:
		return "param"
	case FieldListTypeResult:
		return "result"
	}
	return ""
}

// EnhanceParameterNames enhance the parameter names if they are missing
func EnhanceParameterNames(fields *dst.FieldList, fieldType FieldListType) []*ParameterInfo {
	if fields == nil {
		return nil
	}
	result := make([]*ParameterInfo, 0)
	for i, f := range fields.List {
		var defineName string
		switch fieldType {
		case FieldListTypeParam:
			defineName = fmt.Sprintf("skywalking_param_%d", i)
		case FieldListTypeResult:
			defineName = fmt.Sprintf("skywalking_result_%d", i)
		case FieldListTypeRecv:
			defineName = fmt.Sprintf("skywalking_recv_%d", i)
		}
		if len(f.Names) == 0 {
			f.Names = []*dst.Ident{{Name: defineName}}
			result = append(result, newParameterInfo(defineName, f.Type))
		} else {
			for _, n := range f.Names {
				if n.Name == "_" {
					*n = *dst.NewIdent(defineName)
					break
				}
			}

			for _, n := range f.Names {
				result = append(result, newParameterInfo(n.Name, f.Type))
			}
		}
	}
	return result
}

func EnhanceParameterNamesWithPackagePrefix(pkg string, fields *dst.FieldList, fieldListType FieldListType) []*PackagedParameterInfo {
	params := EnhanceParameterNames(fields, fieldListType)
	result := make([]*PackagedParameterInfo, 0)
	for _, p := range params {
		result = append(result, &PackagedParameterInfo{ParameterInfo: *p, PackageName: pkg})
	}
	return result
}

func GoStringToStats(goString string) []dst.Stmt {
	parsed, err := decorator.Parse(fmt.Sprintf(`
package main
func main() {
%s
}`, goString))
	if err != nil {
		panic(fmt.Sprintf("parsing go failure: %v\n%s", err, goString))
	}

	return parsed.Decls[0].(*dst.FuncDecl).Body.List
}

func GoStringToDecls(goString string) []dst.Decl {
	parsed, err := decorator.Parse(fmt.Sprintf(`
package main
%s`, goString))
	if err != nil {
		panic(fmt.Sprintf("parsing go failure: %v\n%s", err, goString))
	}

	return parsed.Decls
}

func InsertStmtsBeforeBody(body *dst.BlockStmt, tmpl string, data interface{}) {
	body.List = append(GoStringToStats(ExecuteTemplate(tmpl, data)), body.List...)
}

func newParameterInfo(name string, tp dst.Expr) *ParameterInfo {
	result := &ParameterInfo{
		Name:     name,
		Type:     tp,
		TypeName: GenerateTypeNameByExp(tp),
	}
	return result
}

func (p *PackagedParameterInfo) PackagedType() dst.Expr {
	return addPackagePrefixForArgsAndClone(p.PackageName, p.Type)
}

func (p *PackagedParameterInfo) PackagedTypeName() string {
	return GenerateTypeNameByExp(p.PackagedType())
}

// nolint
func GenerateTypeNameByExp(exp dst.Expr) string {
	var data string
	switch n := exp.(type) {
	case *dst.StarExpr:
		data = "*" + GenerateTypeNameByExp(n.X)
	case *dst.TypeAssertExpr:
		data = GenerateTypeNameByExp(n.X)
	case *dst.InterfaceType:
		data = interfaceName
	case *dst.Ident:
		data = n.Name
	case *dst.SelectorExpr:
		data = GenerateTypeNameByExp(n.X) + "." + GenerateTypeNameByExp(n.Sel)
	case *dst.Ellipsis:
		data = "[]" + GenerateTypeNameByExp(n.Elt)
	case *dst.ArrayType:
		data = "[]" + GenerateTypeNameByExp(n.Elt)
	case *dst.FuncType:
		data = "func("
		if n.Params != nil && len(n.Params.List) > 0 {
			for i, f := range n.Params.List {
				if i > 0 {
					data += parameterAppender
				}
				data += GenerateTypeNameByExp(f.Type)
			}
		}
		data += ")"
		if n.Results != nil && len(n.Results.List) > 0 {
			data += "("
			for i, f := range n.Results.List {
				if i > 0 {
					data += parameterAppender
				}
				data += GenerateTypeNameByExp(f.Type)
			}
			data += ")"
		}
	case *dst.ChanType:
		if n.Dir == dst.SEND {
			data += token.CHAN.String() + token.ARROW.String()
		} else if n.Dir == dst.RECV {
			data += token.ARROW.String() + token.CHAN.String()
		} else {
			data += token.CHAN.String()
		}
		data += " " + GenerateTypeNameByExp(n.Value)
		return data
	default:
		return ""
	}
	return data
}

func addPackagePrefixForArgsAndClone(pkg string, tp dst.Expr) dst.Expr {
	switch t := tp.(type) {
	case *dst.Ident:
		if IsBasicDataType(t.Name) {
			return dst.Clone(tp).(dst.Expr)
		}
		// otherwise, add the package prefix
		return &dst.SelectorExpr{
			X:   dst.NewIdent(pkg),
			Sel: dst.NewIdent(t.Name),
		}
	case *dst.StarExpr:
		expr := dst.Clone(tp).(*dst.StarExpr)
		expr.X = addPackagePrefixForArgsAndClone(pkg, t.X)
		return expr
	case *dst.Ellipsis:
		expr := dst.Clone(tp).(*dst.Ellipsis)
		expr.Elt = addPackagePrefixForArgsAndClone(pkg, t.Elt)
		return expr
	case *dst.SelectorExpr:
		exp := dst.Clone(tp).(*dst.SelectorExpr)
		// if also contains a package prefix, then it could be reffed a package with same name
		// Such as current package name is "grpc", and ref another package named "grpc"
		// Usually it's used on a wrapper plugin
		if sel, ok := t.X.(*dst.Ident); ok && sel.Name == pkg {
			exp.X = dst.NewIdent(OtherPackageRefPrefix + pkg)
		}
		return exp
	case *dst.ChanType:
		expr := dst.Clone(tp).(*dst.ChanType)
		return expr
	default:
		return dst.Clone(tp).(dst.Expr)
	}
}
