// Copyright 2020 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 lib

import (
	"fmt"
	"strconv"
	"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"
)

func BuildValueUnowned(value gidlir.Value, decl gidlmixer.Declaration, handleRepr HandleRepr) (string, string) {
	var builder unownedBuilder
	builder.handleRepr = handleRepr
	valueVar := builder.visit(value, decl)
	valueBuild := builder.String()
	return valueBuild, valueVar
}

type unownedBuilder struct {
	strings.Builder
	varidx     int
	handleRepr HandleRepr
}

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

func (b *unownedBuilder) newVar() string {
	b.varidx++
	return fmt.Sprintf("v%d", b.varidx)
}

func primitiveTypeName(subtype fidlgen.PrimitiveSubtype) string {
	switch subtype {
	case fidlgen.Bool:
		return "bool"
	case fidlgen.Uint8, fidlgen.Uint16, fidlgen.Uint32, fidlgen.Uint64,
		fidlgen.Int8, fidlgen.Int16, fidlgen.Int32, fidlgen.Int64:
		return fmt.Sprintf("%s_t", subtype)
	case fidlgen.Float32:
		return "float"
	case fidlgen.Float64:
		return "double"
	default:
		panic(fmt.Sprintf("unexpected subtype %s", subtype))
	}
}

func (b *unownedBuilder) visit(value gidlir.Value, decl gidlmixer.Declaration) string {
	switch value := value.(type) {
	case bool:
		return fmt.Sprintf("%t", value)
	case uint64:
		return fmt.Sprintf("%s(%dll)", typeName(decl), value)
	case int64:
		if value == -9223372036854775808 {
			return fmt.Sprintf("%s(-9223372036854775807ll - 1)", typeName(decl))
		}
		return fmt.Sprintf("%s(%dll)", typeName(decl), value)
	case float64:
		switch decl := decl.(type) {
		case *gidlmixer.FloatDecl:
			switch decl.Subtype() {
			case fidlgen.Float32:
				s := fmt.Sprintf("%g", value)
				if strings.Contains(s, ".") {
					return fmt.Sprintf("%sf", s)
				}
				return s
			case fidlgen.Float64:
				return fmt.Sprintf("%g", value)
			}
		}
	case gidlir.RawFloat:
		switch decl.(*gidlmixer.FloatDecl).Subtype() {
		case fidlgen.Float32:
			return fmt.Sprintf("([] { uint32_t u = %#b; float f; memcpy(&f, &u, sizeof(float)); return f; })()", value)
		case fidlgen.Float64:
			return fmt.Sprintf("([] { uint64_t u = %#b; double d; memcpy(&d, &u, sizeof(double)); return d; })()", value)
		}
	case string:
		return fmt.Sprintf("fidl::StringView(%s)", strconv.Quote(value))
	case gidlir.HandleWithRights:
		if b.handleRepr == HandleReprDisposition || b.handleRepr == HandleReprInfo {
			return fmt.Sprintf("%s(handle_defs[%d].handle)", typeName(decl), value.Handle)
		}
		return fmt.Sprintf("%s(handle_defs[%d])", typeName(decl), value.Handle)
	case gidlir.Record:
		switch decl := decl.(type) {
		case *gidlmixer.StructDecl:
			return b.visitStruct(value, decl)
		case *gidlmixer.TableDecl:
			return b.visitTable(value, decl)
		case *gidlmixer.UnionDecl:
			return b.visitUnion(value, decl)
		}
	case []gidlir.Value:
		switch decl := decl.(type) {
		case *gidlmixer.ArrayDecl:
			return b.visitArray(value, decl)
		case *gidlmixer.VectorDecl:
			return b.visitVector(value, decl)
		}
	case nil:
		return fmt.Sprintf("%s{}", typeName(decl))
	}
	panic(fmt.Sprintf("not implemented: %T", value))
}

func (b *unownedBuilder) visitStruct(value gidlir.Record, decl *gidlmixer.StructDecl) string {
	containerVar := b.newVar()
	b.write(
		"%s %s{};\n", declName(decl), containerVar)
	for _, field := range value.Fields {
		fieldDecl, ok := decl.Field(field.Key.Name)
		if !ok {
			panic(fmt.Sprintf("field %s not found", field.Key.Name))
		}

		stringBeforeVisitField := b.String()
		fieldValue := b.visit(field.Value, fieldDecl)
		// if visiting the field does not write any data to the string builder
		// then its return value is a temporary object and so cannot be moved
		// (which will prevent copy elision)
		if stringBeforeVisitField == b.String() {
			b.write("%s.%s = %s;\n", containerVar, field.Key.Name, fieldValue)
		} else {
			b.write("%s.%s = std::move(%s);\n", containerVar, field.Key.Name, fieldValue)
		}
	}
	var result string
	if decl.IsNullable() {
		viewVar := b.newVar()
		b.write("auto %s = fidl::ObjectView<%s>::FromExternal(&%s);\n", viewVar, typeNameIgnoreNullable(decl), containerVar)
		result = viewVar
	} else {
		result = containerVar
	}
	return fmt.Sprintf("std::move(%s)", result)
}

func (b *unownedBuilder) visitTable(value gidlir.Record, decl *gidlmixer.TableDecl) string {
	frameVar := b.newVar()

	b.write(
		"fidl::WireTableFrame<%s> %s;\n", declName(decl), frameVar)

	tableVar := b.newVar()

	b.write(
		"%s %s(::fidl::ObjectView<::fidl::WireTableFrame<%s>>::FromExternal(&%s));\n", declName(decl), tableVar, declName(decl), frameVar)

	for _, field := range value.Fields {
		if field.Key.IsUnknown() {
			panic("LLCPP does not support constructing unknown fields")
		}
		fieldDecl, ok := decl.Field(field.Key.Name)
		if !ok {
			panic(fmt.Sprintf("field %s not found", field.Key.Name))
		}
		fieldVar := b.visit(field.Value, fieldDecl)
		storageVar := b.newVar()
		b.write("auto %s = std::move(%s);\n", storageVar, fieldVar)
		if fieldDecl.IsInlinableInEnvelope() {
			b.write(
				"%s.set_%s(%s);\n", tableVar, field.Key.Name, storageVar)
		} else {
			b.write(
				"%s.set_%s(fidl::ObjectView<%s>::FromExternal(&%s));\n", tableVar, field.Key.Name, typeName(fieldDecl), storageVar)
		}
	}

	return fmt.Sprintf("std::move(%s)", tableVar)
}

func (b *unownedBuilder) visitUnion(value gidlir.Record, decl *gidlmixer.UnionDecl) string {
	containerVar := b.newVar()

	b.write(
		"%s %s;\n", declName(decl), containerVar)

	for _, field := range value.Fields {
		if field.Key.IsUnknown() {
			panic("LLCPP does not support constructing unknown fields")
		}
		fieldDecl, ok := decl.Field(field.Key.Name)
		if !ok {
			panic(fmt.Sprintf("field %s not found", field.Key.Name))
		}
		fieldVar := b.visit(field.Value, fieldDecl)
		storageVar := b.newVar()
		b.write("auto %s = std::move(%s);\n", storageVar, fieldVar)
		if fieldDecl.IsInlinableInEnvelope() {
			b.write(
				"%s.set_%s(%s);\n", containerVar, field.Key.Name, storageVar)

		} else {
			b.write(
				"%s.set_%s(fidl::ObjectView<%s>::FromExternal(&%s));\n", containerVar, field.Key.Name, typeName(fieldDecl), storageVar)
		}
	}
	return fmt.Sprintf("std::move(%s)", containerVar)
}

func (b *unownedBuilder) buildListItems(value []gidlir.Value, decl gidlmixer.ListDeclaration) []string {
	var elements []string
	elemDecl := decl.Elem()
	for _, item := range value {
		elements = append(elements, fmt.Sprintf("%s", b.visit(item, elemDecl)))
	}
	return elements
}

func (b *unownedBuilder) visitArray(value []gidlir.Value, decl *gidlmixer.ArrayDecl) string {
	elements := b.buildListItems(value, decl)
	sliceVar := b.newVar()
	b.write("FIDL_ALIGNDECL auto %s = %s{%s};\n",
		sliceVar, typeName(decl), strings.Join(elements, ", "))
	return sliceVar
}

func (b *unownedBuilder) visitVector(value []gidlir.Value, decl *gidlmixer.VectorDecl) string {
	if len(value) == 0 {
		sliceVar := b.newVar()
		b.write("auto %s = %s();\n",
			sliceVar, typeName(decl))
		return sliceVar
	}
	elements := b.buildListItems(value, decl)
	arrayVar := b.newVar()
	b.write("auto %s = fidl::Array<%s, %d>{%s};\n",
		arrayVar, typeName(decl.Elem()), len(elements), strings.Join(elements, ", "))
	sliceVar := b.newVar()
	b.write("auto %s = fidl::VectorView<%s>::FromExternal(%s.data(), %d);\n", sliceVar,
		typeName(decl.Elem()), arrayVar, len(elements))
	return fmt.Sprintf("std::move(%s)", sliceVar)
}
