// 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 fidlgen_cpp

import (
	"encoding/binary"
	"fmt"
	"strings"

	"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
)

type Struct struct {
	Attributes
	fidlgen.Resourceness
	nameVariants
	AnonymousChildren   []ScopedLayout
	CodingTableType     name
	Members             []StructMember
	PaddingV1           []StructPadding
	PaddingV2           []StructPadding
	BackingBufferTypeV1 string
	BackingBufferTypeV2 string
	IsInResult          bool
	ParametersTupleDecl name
	// Full decls needed to check if a type is memcpy compatible.
	// Only set if it may be possible for a type to be memcpy compatible,
	// e.g. has no padding.
	// See the struct template for usage.
	FullDeclMemcpyCompatibleDeps []nameVariants

	TypeShapeV1 TypeShape
	TypeShapeV2 TypeShape

	isEmptyStruct                bool
	isAnonymousRequestOrResponse bool
}

func (*Struct) Kind() declKind {
	return Kinds.Struct
}

// AsParameters flattens the struct's members into a parameter list.
func (s *Struct) AsParameters(_ *Type, _ *HandleInformation) []Parameter {
	var out []Parameter
	for _, sm := range s.Members {
		out = append(out, sm.AsParameter())
	}
	return out
}

// SetInResult marks the struct as being used in as the success variant in a
// method Result, and takes note of the tuple declaration of the result's
// parameters. Because a named struct may be in multiple results, every
// call to this function after the first one per instance is a no-op, since the
// struct would have already been marked with the same information.
func (s *Struct) SetInResult(result *Result) {
	if !s.IsInResult {
		s.IsInResult = true
		s.ParametersTupleDecl = result.ValueTupleDecl
	}
}

func (s *Struct) IsEmpty() bool {
	return s.isEmptyStruct
}

var _ Kinded = (*Struct)(nil)
var _ namespaced = (*Struct)(nil)

type StructMember struct {
	Attributes
	nameVariants
	Type              Type
	DefaultValue      ConstantValue
	OffsetV1          int
	OffsetV2          int
	HandleInformation *HandleInformation
	NaturalConstraint string
	WireConstraint    string
}

var _ Member = (*StructMember)(nil)

func (sm StructMember) AsParameter() Parameter {
	return Parameter{
		nameVariants:      sm.nameVariants,
		Type:              sm.Type,
		OffsetV1:          sm.OffsetV1,
		OffsetV2:          sm.OffsetV2,
		HandleInformation: sm.HandleInformation,
		WireConstraint:    sm.WireConstraint,
	}
}

func (sm StructMember) NameAndType() (string, Type) {
	return sm.Name(), sm.Type
}

func (sm StructMember) StorageName() string {
	return sm.Name() + "_"
}

// NaturalInitializer is an expression in natural types for initializing the
// struct member within its struct field definition. May be empty if we choose
// to delegate to the default constructor of the member type.
func (sm StructMember) NaturalInitializer() string {
	var unwrapArray func(ty *Type) string
	unwrapArray = func(ty *Type) string {
		if ty.IsPrimitiveType() {
			// Zero initialize them.
			return "{}"
		}
		if ty.Kind == TypeKinds.Array {
			return unwrapArray(ty.ElementType)
		}
		return ""
	}

	if !sm.Type.Nullable {
		return unwrapArray(&sm.Type)
	}
	return ""
}

// NaturalPossiblyInvalidDefaultInitializer is an expression in natural types
// for how to default initialize the struct member within its struct field
// definition. May result in an invalid object if it has a strict union
// somewhere.
func (sm StructMember) NaturalPossiblyInvalidDefaultInitializer() string {
	if !sm.Type.Nullable {
		switch sm.Type.Kind {
		case TypeKinds.Array:
			return fmt.Sprintf("::fidl::internal::DefaultConstructPossiblyInvalidObject<%s>::Make()", sm.Type.Unified)
		case TypeKinds.Struct, TypeKinds.Table, TypeKinds.Union:
			return "::fidl::internal::DefaultConstructPossiblyInvalidObjectTag{}"
		}
	}
	return "{}"
}

func (c *compiler) compileStructMember(val fidlgen.StructMember) StructMember {
	t := c.compileType(val.Type)

	defaultValue := ConstantValue{}
	if val.MaybeDefaultValue != nil {
		defaultValue = c.compileConstant(*val.MaybeDefaultValue, &t, val.Type)
	}

	return StructMember{
		Attributes:        Attributes{val.Attributes},
		nameVariants:      structMemberContext.transform(val.Name),
		Type:              t,
		DefaultValue:      defaultValue,
		OffsetV1:          val.FieldShapeV1.Offset,
		OffsetV2:          val.FieldShapeV2.Offset,
		HandleInformation: c.fieldHandleInformation(&val.Type),
		NaturalConstraint: t.NaturalFieldConstraint,
		WireConstraint:    t.WireFieldConstraint,
	}
}

type StructPadding struct {
	Offset   int
	MaskType string
	Mask     string
}

func toStructPadding(in fidlgen.PaddingMarker) StructPadding {
	switch len(in.Mask) {
	case 2:
		return StructPadding{
			Offset:   in.Offset,
			MaskType: "uint16_t",
			Mask:     fmt.Sprintf("0x%04x", binary.LittleEndian.Uint16(in.Mask)),
		}
	case 4:
		return StructPadding{
			Offset:   in.Offset,
			MaskType: "uint32_t",
			Mask:     fmt.Sprintf("0x%08x", binary.LittleEndian.Uint32(in.Mask)),
		}
	case 8:
		return StructPadding{
			Offset:   in.Offset,
			MaskType: "uint64_t",
			Mask:     fmt.Sprintf("0x%016xull", binary.LittleEndian.Uint64(in.Mask)),
		}
	default:
		panic("unexpected mask size")
	}
}

func toStructPaddings(in []fidlgen.PaddingMarker) []StructPadding {
	var out []StructPadding
	for _, m := range in {
		out = append(out, toStructPadding(m))
	}
	return out
}

func (c *compiler) compileStruct(val fidlgen.Struct) *Struct {
	name := c.compileNameVariants(val.Name)
	codingTableType := name.Wire.ns.member(c.compileCodingTableType(val.Name))
	r := Struct{
		Attributes:        Attributes{val.Attributes},
		AnonymousChildren: c.getAnonymousChildren(val),
		TypeShapeV1:       TypeShape{val.TypeShapeV1},
		TypeShapeV2:       TypeShape{val.TypeShapeV2},
		Resourceness:      val.Resourceness,
		nameVariants:      name,
		CodingTableType:   codingTableType,
		Members:           []StructMember{},
		BackingBufferTypeV1: computeAllocation(
			TypeShape{val.TypeShapeV1}.MaxTotalSize(), TypeShape{val.TypeShapeV1}.MaxHandles, boundednessBounded).
			BackingBufferType(),
		BackingBufferTypeV2: computeAllocation(
			TypeShape{val.TypeShapeV2}.MaxTotalSize(), TypeShape{val.TypeShapeV2}.MaxHandles, boundednessBounded).
			BackingBufferType(),
		IsInResult: false,
		PaddingV1:  toStructPaddings(val.BuildPaddingMarkers(fidlgen.WireFormatVersionV1)),
		PaddingV2:  toStructPaddings(val.BuildPaddingMarkers(fidlgen.WireFormatVersionV2)),
	}

	for _, v := range val.Members {
		r.Members = append(r.Members, c.compileStructMember(v))
	}

	if len(r.Members) == 0 {
		r.isEmptyStruct = true
		r.Members = []StructMember{
			c.compileStructMember(fidlgen.EmptyStructMember("__reserved")),
		}
	}

	// Construct a deduped list of decls for IsMemcpyCompatible template definitions.
	seen := make(map[string]struct{})
	for _, member := range r.Members {
		if _, ok := seen[member.Type.HLCPP.String()]; ok {
			continue
		}
		seen[member.Type.HLCPP.String()] = struct{}{}

		// The dangerous identifiers test package contains identifiers that won't compile.
		// e.g. ::fidl::test::dangerous::struct::types::camel::Interface gives an
		// "expected unqualified-id" error because of "struct".
		// There isn't an easily accessible dangerous identifiers list to replace identifiers.
		if strings.Contains(member.Type.HLCPP.String(), "::fidl::test::dangerous::") {
			continue
		}

		r.FullDeclMemcpyCompatibleDeps = append(r.FullDeclMemcpyCompatibleDeps, member.Type.nameVariants)
	}

	return &r
}
