// Copyright 2022 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

import (
	"bytes"
	"fmt"
)

// In the masks used in the following functions, bytes requiring padding are marked 0xff and
// bytes not requiring padding are marked 0x00.

func (s Struct) populateFullStructMaskForStruct(mask []byte, flatten bool, getTypeShape func(Struct) TypeShape, getFieldShape func(StructMember) FieldShape, resolveStruct func(identifier EncodedCompoundIdentifier) *Struct) {
	paddingEnd := getTypeShape(s).InlineSize - 1
	for i := len(s.Members) - 1; i >= 0; i-- {
		member := s.Members[i]
		fieldShape := getFieldShape(member)
		if flatten {
			s.populateFullStructMaskForType(mask[fieldShape.Offset:paddingEnd+1], &member.Type, flatten, getTypeShape, getFieldShape, resolveStruct)
		}
		for j := 0; j < fieldShape.Padding; j++ {
			mask[paddingEnd-j] = 0xff
		}
		paddingEnd = fieldShape.Offset - 1
	}
}

func (s Struct) populateFullStructMaskForType(mask []byte, typ *Type, flatten bool, getTypeShape func(Struct) TypeShape, getFieldShape func(StructMember) FieldShape, resolveStruct func(identifier EncodedCompoundIdentifier) *Struct) {
	if typ.Nullable {
		return
	}
	switch typ.Kind {
	case ArrayType:
		elemByteSize := len(mask) / *typ.ElementCount
		for i := 0; i < *typ.ElementCount; i++ {
			s.populateFullStructMaskForType(mask[i*elemByteSize:(i+1)*elemByteSize], typ.ElementType, flatten, getTypeShape, getFieldShape, resolveStruct)
		}
	case IdentifierType:
		sv := resolveStruct(typ.Identifier)
		if sv != nil {
			sv.populateFullStructMaskForStruct(mask, flatten, getTypeShape, getFieldShape, resolveStruct)
		}
	}
}

type PaddingMarker struct {
	// Offset into the struct (0 is the start of the struct).
	Offset int
	// Mask, where a 1-bit means the bit in the input value should be zero.
	Mask []byte
}

func (s Struct) buildPaddingMarkers(flatten bool, getTypeShape func(Struct) TypeShape, getFieldShape func(StructMember) FieldShape, resolveStruct func(identifier EncodedCompoundIdentifier) *Struct) []PaddingMarker {
	var paddingMarkers []PaddingMarker

	// Construct a mask across the whole struct with 0xff bytes where there is padding.
	fullStructMask := make([]byte, getTypeShape(s).InlineSize)
	s.populateFullStructMaskForStruct(fullStructMask, flatten, getTypeShape, getFieldShape, resolveStruct)

	// Split up the mask into aligned integer mask segments that can be outputted in the
	// fidl_struct! macro.
	// Only the sections needing padding are outputted.
	// e.g. 00ffff0000ffff000000000000000000 -> 00ffff0000ffff00, 0000000000000000
	//                                       -> []PaddingMarker{0, []byte{0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00}}
	extractNonzeroSliceOffsets := func(stride int) []int {
		var offsets []int
		for endi := stride - 1; endi < len(fullStructMask); endi += stride {
			i := endi - (stride - 1)
			if bytes.Contains(fullStructMask[i:i+stride], []byte{0xff}) {
				offsets = append(offsets, i)
			}
		}
		return offsets
	}
	zeroSlice := func(s []byte) {
		for i := range s {
			s[i] = 0
		}
	}
	if getTypeShape(s).Alignment >= 8 {
		for _, i := range extractNonzeroSliceOffsets(8) {
			s := fullStructMask[i : i+8]
			m := make([]byte, 8)
			copy(m, s)
			paddingMarkers = append(paddingMarkers, PaddingMarker{
				Offset: i,
				Mask:   m,
			})
			zeroSlice(s) // Reset the buffer for the next iteration.
		}
	}
	if getTypeShape(s).Alignment >= 4 {
		for _, i := range extractNonzeroSliceOffsets(4) {
			s := fullStructMask[i : i+4]
			m := make([]byte, 4)
			copy(m, s)
			paddingMarkers = append(paddingMarkers, PaddingMarker{
				Offset: i,
				Mask:   m,
			})
			zeroSlice(s) // Reset the buffer for the next iteration.
		}
	}
	for _, i := range extractNonzeroSliceOffsets(2) {
		s := fullStructMask[i : i+2]
		m := make([]byte, 2)
		copy(m, s)
		paddingMarkers = append(paddingMarkers, PaddingMarker{
			Offset: i,
			Mask:   m,
		})
		zeroSlice(s) // Reset the buffer for the next iteration.
	}
	if bytes.Contains(fullStructMask, []byte{0xff}) {
		// This shouldn't be possible because it requires an alignment 1 struct to have padding.
		panic(fmt.Sprintf("expected mask to be zero, was %v", fullStructMask))
	}
	return paddingMarkers
}

type WireFormatVersion int

const (
	_ = iota
	WireFormatVersionV1
	WireFormatVersionV2
)

func getTypeShapeFunc(wireFormatVersion WireFormatVersion) func(Struct) TypeShape {
	switch wireFormatVersion {
	case WireFormatVersionV1:
		return func(s Struct) TypeShape {
			return s.TypeShapeV1
		}
	case WireFormatVersionV2:
		return func(s Struct) TypeShape {
			return s.TypeShapeV2
		}
	default:
		panic("unknown wire format version")
	}
}

func getFieldShapeFunc(wireFormatVersion WireFormatVersion) func(StructMember) FieldShape {
	switch wireFormatVersion {
	case WireFormatVersionV1:
		return func(s StructMember) FieldShape {
			return s.FieldShapeV1
		}
	case WireFormatVersionV2:
		return func(s StructMember) FieldShape {
			return s.FieldShapeV2
		}
	default:
		panic("unknown wire format version")
	}
}

func (s Struct) BuildPaddingMarkers(wireFormatVersion WireFormatVersion) []PaddingMarker {
	return s.buildPaddingMarkers(false, getTypeShapeFunc(wireFormatVersion), getFieldShapeFunc(wireFormatVersion), nil)
}

func (s Struct) BuildFlattenedPaddingMarkers(wireFormatVersion WireFormatVersion, resolveStruct func(identifier EncodedCompoundIdentifier) *Struct) []PaddingMarker {
	return s.buildPaddingMarkers(true, getTypeShapeFunc(wireFormatVersion), getFieldShapeFunc(wireFormatVersion), resolveStruct)
}
