// Copyright 2021 The Fuchsia 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 rust

import (
	"fmt"
	"strings"

	gidlir "go.fuchsia.dev/fuchsia/tools/fidl/gidl/ir"
	gidlmixer "go.fuchsia.dev/fuchsia/tools/fidl/gidl/mixer"
	"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
)

// Returns Rust code that resets all handles in expr (an expression of type
// "&mut _") to the invalid handle without closing the original handles.
func buildForgetHandles(expr string, value gidlir.Value, decl gidlmixer.Declaration) string {
	var b forgetHandleBuilder
	b.visit(expr, value, decl)
	return strings.TrimSpace(b.String())
}

type forgetHandleBuilder struct {
	strings.Builder
}

func (b *forgetHandleBuilder) write(format string, args ...interface{}) {
	b.WriteString(fmt.Sprintf(format, args...))
}

func (b *forgetHandleBuilder) visit(expr string, value gidlir.Value, decl gidlmixer.Declaration) {
	switch value := value.(type) {
	case gidlir.Handle, gidlir.HandleWithRights:
		b.write("std::mem::forget(std::mem::replace(%s, Handle::invalid().into()));\n", expr)
	case gidlir.Record:
		decl := decl.(gidlmixer.RecordDeclaration)
		switch decl.(type) {
		case *gidlmixer.StructDecl:
			for _, field := range value.Fields {
				fieldDecl, ok := decl.Field(field.Key.Name)
				if !ok {
					panic(fmt.Sprintf("field %s not found", field.Key.Name))
				}
				b.visit(fmt.Sprintf("(&mut %s.%s)", expr, field.Key.Name), field.Value, fieldDecl)
			}
		case *gidlmixer.TableDecl:
			hasUnknown := false
			for _, field := range value.Fields {
				if field.Key.IsUnknown() {
					hasUnknown = true
					continue
				}
				fieldDecl, ok := decl.Field(field.Key.Name)
				if !ok {
					panic(fmt.Sprintf("field %s not found", field.Key.Name))
				}
				b.visit(fmt.Sprintf("%s.%s.as_mut().unwrap()", expr, field.Key.Name), field.Value, fieldDecl)
			}
			if decl.IsResourceType() && hasUnknown {
				b.write(`for data in %s.unknown_data.as_mut().unwrap().values_mut() {
	for h in data.handles.drain(..) { std::mem::forget(h); }
}
`, expr)
			}
		case *gidlmixer.UnionDecl:
			if len(value.Fields) != 1 {
				panic(fmt.Sprintf("union has %d fields, expected 1", len(value.Fields)))
			}
			field := value.Fields[0]
			if field.Key.IsKnown() {
				fieldDecl, ok := decl.Field(field.Key.Name)
				fieldName := fidlgen.ToUpperCamelCase(field.Key.Name)
				if !ok {
					panic(fmt.Sprintf("field %s not found", field.Key.Name))
				}
				// Use another builder so that we only emit the match statement
				// if there are any handles within to forget.
				var inner forgetHandleBuilder
				inner.visit("x", field, fieldDecl)
				if inner.Len() == 0 {
					break
				}
				b.write(`match %s {
	%s::%s(x) => {
		%s
	}
	_ => unreachable!(),
}
`, expr, declName(decl), fieldName, inner.String())
			} else {
				unknownData := field.Value.(gidlir.UnknownData)
				if len(unknownData.Handles) != 0 {
					if !decl.IsResourceType() {
						panic("non-resource type should not have unknown handles")
					}
					b.write(`match %s {
	#[allow(deprecated)]
	%s::__Unknown { data, .. } => {
		for h in data.handles.drain(..) { std::mem::forget(h); }
	}
	_ => unreachable!(),
}
`, expr, declName(decl))
				}
			}
		}
	case []gidlir.Value:
		elemDecl := decl.(gidlmixer.ListDeclaration).Elem()
		for i, elem := range value {
			b.visit(fmt.Sprintf("(&mut %s[%d])", expr, i), elem, elemDecl)
		}
	}
}
