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

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

package swift

import (
	"bytes"
	"log"

	"fmt"

	"v.io/v23/vdl"
	"v.io/x/ref/lib/vdl/compile"
)

const structTmpl = `{{ .Doc }}///
/// Auto-generated from {{.VdlTypeName}}
{{ .AccessModifier }} class {{.Name}} : VdlStruct, CustomDebugStringConvertible {{ if .IsHashable }}, Hashable {{ end }}{
    /// Vdl type for {@link {{.Name}}}.
    {{ .AccessModifier }} static let vdlTypeName = "{{.VdlTypeName}}"

    {{/* Field declarations */}}
    {{ range $index, $field := .Fields }}
    /// "{{$field.VdlName}}" index {{$index}}
    var {{$field.Name}}: {{$field.Type}}
    {{ end }}

    {{ .AccessModifier }} init({{ range $index, $field := .Fields }}{{ if gt $index 0 }},{{ end }}
        {{$field.Name}}: {{$field.Type}}{{end}}) {

      {{range $field := .Fields}}self.{{$field.Name}} = {{$field.Name}}
      {{end}}{{/* range $field */}}
    }
    {{ if .IsHashable }}
    {{ .AccessModifier }} var hashValue: Int {
      var result = 1
      let prime = 31
      {{ range $field := .Fields }}result = prime &* result &+ Int({{$field.HashcodeComputation}})
      {{ end }}
      return result
    }
    {{ end }}

    {{ .AccessModifier }} var description: String {
      return "{{ .VdlTypeName }}"
    }

    {{ .AccessModifier }} var debugDescription: String {
      var result = "[{{ .VdlTypeName }} "
      {{ range $index, $field := .Fields }}
      {{ if gt $index 0 }}result += ", "{{ end }}
      {{ if .IsAny }}
      result += "{{$field.Name}}:" + (({{$field.Name}} as? CustomDebugStringConvertible)?.debugDescription ?? "\({{$field.Name}})")
      {{ else }}
      result += "{{$field.Name}}:" + {{$field.Name}}.debugDescription
      {{ end }}{{/* IsAny */}}
      {{ end }}{{/* range over fields */}}
      return result + "]"
    }
}

{{ if .IsHashable }}
{{ .AccessModifier }} func ==(lhs: {{.Name}}, rhs: {{.Name}}) -> Bool {
	{{ range $field := .Fields }}
	{{ if $field.IsOptional }}
	switch (lhs.{{$field.Name}}, rhs.{{$field.Name}}) {
		case (nil, nil): break
		case (nil, _): return false
		case (_, nil): return false
		case let (lfield?, rfield?):
		 	if lfield != rfield {
		 	  return false
		 	}
		default: break
	}
	{{ else }}
	if lhs.{{$field.Name}} != rhs.{{$field.Name}} {
		return false
	}
	{{ end }} {{/* optional comparison */}}
	{{ end }} {{/* range over fields */}}
	return true
}{{ end }}`

type structDefinitionField struct {
	AccessModifier      string
	Class               string
	Doc                 string
	HashcodeComputation string
	IsAny               bool
	IsOptional          bool
	Name                string
	Type                string
	VdlName             string
}

func swiftFieldArgStr(tdef *compile.TypeDef, ctx *swiftContext) string {
	var buf bytes.Buffer
	for i := 0; i < tdef.Type.NumField(); i++ {
		if i > 0 {
			buf.WriteString(", ")
		}
		fld := tdef.Type.Field(i)
		buf.WriteString(ctx.swiftType(fld.Type))
		buf.WriteString(" ")
		buf.WriteString(swiftVariableName(tdef, fld))
	}
	return buf.String()
}

// genSwiftStructFile generates the Swift class file for the provided user-defined type.
func genSwiftStructTdef(tdef *compile.TypeDef, ctx *swiftContext) string {
	isHashable := isTypeHashable(tdef.Type, make(map[*vdl.Type]bool))
	fields := make([]structDefinitionField, tdef.Type.NumField())
	for i := 0; i < tdef.Type.NumField(); i++ {
		fld := tdef.Type.Field(i)
		hashComp := ""
		if isHashable {
			var err error
			hashComp, err = ctx.swiftHashCode("self."+swiftVariableName(tdef, fld), fld.Type)
			if err != nil {
				panic(fmt.Sprintf("Unable to compute hashcode: %v", err))
			}
		}
		fields[i] = structDefinitionField{
			AccessModifier:      swiftAccessModifierForName(fld.Name),
			Class:               ctx.swiftType(fld.Type),
			Doc:                 swiftDoc(tdef.FieldDoc[i], tdef.FieldDocSuffix[i]),
			HashcodeComputation: hashComp,
			IsAny:               fld.Type.Kind() == vdl.Any,
			IsOptional:          fld.Type.Kind() == vdl.Optional,
			Name:                swiftVariableName(tdef, fld),
			Type:                ctx.swiftType(fld.Type),
			VdlName:             fld.Name,
		}
	}

	// Determine if we can create a hashValue out of this. A hashValue implies
	// equality and access to primitives in a useful way. With Any types we cannot
	// do this. One plausible hack is to use "\(x)", but if for some reason the
	// underlying type doesn't convey enough information in its forced string
	// conversion then we're not properly comparing.
	data := struct {
		AccessModifier string
		Doc            string
		Fields         []structDefinitionField
		FieldsAsArgs   string
		IsHashable     bool
		Name           string
		Source         string
		VdlTypeName    string
		VdlTypeString  string
	}{
		AccessModifier: swiftAccessModifier(tdef),
		Doc:            swiftDoc(tdef.Doc, tdef.DocSuffix),
		Fields:         fields,
		FieldsAsArgs:   swiftFieldArgStr(tdef, ctx),
		IsHashable:     isHashable,
		Name:           ctx.swiftTypeName(tdef),
		Source:         tdef.File.BaseName,
		VdlTypeName:    tdef.Type.Name(),
		VdlTypeString:  tdef.Type.String(),
	}
	var buf bytes.Buffer
	err := parseTmpl("swift struct", structTmpl).Execute(&buf, data)
	if err != nil {
		log.Fatalf("vdl: couldn't execute struct template: %v", err)
	}
	return formatSwiftCode(buf.String())
}
