// Copyright 2021 CloudWeGo Authors
//
// Licensed 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 thriftgo

const RegisterHessian = `
{{- define "register"}}
package {{ .PkgName}}

import (
    "fmt"

	"github.com/pkg/errors"
	"github.com/kitex-contrib/codec-dubbo/pkg/hessian2"
	codec "github.com/kitex-contrib/codec-dubbo/pkg/iface"
)

var objects{{ .IDLName}} = []interface{}{ 
{{- range .Scope.StructLikes}}
    &{{ .GoName}}{},
{{- end}} 
}

func init() {
	hessian2.Register(objects{{ .IDLName}} )
}

{{range .Scope.Services }}
func Get{{.GoName}}IDLAnnotations() map[string][]string {
	return map[string][]string {
        {{- range .Annotations}}
		"{{.Key}}": { {{range .Values}}"{{.}}", {{- end}}},
        {{- end}}
	}
}
{{- end}}

{{- range .Scope.StructLikes}}
{{template "StructLikeProtocol" .}}
{{- end}}

{{- range .Scope.Services}}
{{- range .Functions}}

{{$argType := .ArgType}}
{{$resType := .ResType}}

func (p *{{$argType.GoName}}) Encode(e codec.Encoder) error {
{{- if gt (len $argType.Fields) 0}}
	var err error
{{- end}}
{{- range $argType.Fields}}
{{- $FieldName := .GoName}}
	err = e.Encode(p.{{$FieldName}})
    if err != nil {
    	return err
	}
{{end}}{{/* range .Fields */}}
	return nil
}

func (p *{{$argType.GoName}}) Decode(d codec.Decoder) error {
{{- if gt (len $argType.Fields) 0}}
    var (
		err error
		v interface{}
	)
{{- end}}
{{- range $argType.Fields}}
{{- $Type := .Type }}
{{- $FieldName := .GoName}}
{{- $FieldTypeName := .GoTypeName}}
	v, err = d.Decode()
    if err != nil {
    	return err
	}
    err = hessian2.ReflectResponse(v, &p.{{$FieldName}})
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("invalid data type: %T", v))
	}
{{end}}{{/* range .Fields */}}
	return nil
} {{/* encode decode */}}

func (p *{{$resType.GoName}}) Encode(e codec.Encoder) error {
{{- if gt (len $resType.Fields) 0}}
    var err error
{{- end}}
{{- range $resType.Fields}}
{{- $FieldName := .GoName}}
	err = e.Encode(p.{{$FieldName}})
    if err != nil {
    	return err
	}
{{end}}{{/* range .Fields */}}
	return nil
}

func (p *{{$resType.GoName}}) Decode(d codec.Decoder) error {
{{- if gt (len $resType.Fields) 0}}
    var (
		err error
		v interface{}
	)
{{- end}}
{{- range $resType.Fields}}
{{- $Type := .Type }}
{{- $FieldName := .GoName}}
{{- $FieldTypeName := .GoTypeName}}
	v, err = d.Decode()
    if err != nil {
    	return err
	}
    err = hessian2.ReflectResponse(v, &p.{{$FieldName}})
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("invalid data type: %T", v))
	}
{{end}}{{/* range .Fields */}}
	return nil
} {{/* encode decode */}}

{{- end}}{{/* range Functions */}}
{{- end}}{{/* range .Scope.Service */}}

{{- end}}{{/* define RegisterHessian*/}}
`

const StructLikeProtocol = `
{{define "StructLikeProtocol"}}
{{- $TypeName := .GoName}}
func (p *{{$TypeName}}) Encode(e codec.Encoder) error {
{{- if gt (len .Fields) 0}}
    var err error
{{- end}}
{{- range .Fields}}
{{- $FieldName := .GoName}}
	err = e.Encode(p.{{$FieldName}})
    if err != nil {
    	return err
	}
{{end}}{{/* range .Fields */}}
	return nil
}

func (p *{{$TypeName}}) Decode(d codec.Decoder) error {
{{- if gt (len .Fields) 0}}
	var (
		err error
		v interface{}
	)
{{- end}}
{{- range .Fields}}
{{- $Type := .Type }}
{{- $FieldName := .GoName}}
{{- $FieldTypeName := .GoTypeName}}
	v, err = d.Decode()
    if err != nil {
    	return err
	}
    err = hessian2.ReflectResponse(v, &p.{{$FieldName}})
	if err != nil {
		return errors.Wrap(err, fmt.Sprintf("invalid data type: %T", v))
	}
{{end}}{{/* range .Fields */}}
	return nil
} {{/* encode decode */}}

{{template "JavaClassName" .}}
{{- end}}{{/* define "StructLikeProtocol" */}}
`

const JavaClassName = `
{{define "JavaClassName"}}
{{- $TypeName := .GoName}}
{{- $anno := .Annotations }}
{{- $value := $anno.ILocValueByKey "JavaClassName" 0}}
{{- if ne "" $value}}
func (p *{{$TypeName}}) JavaClassName() string {
	return "{{$value}}"
}
{{- end}}{{/* end if */}}
{{- end}}{{/* end JavaClassName */}}
`
