// Copyright 2024 The Go 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 filedesc

import (
	"fmt"

	"google.golang.org/protobuf/encoding/protowire"
	"google.golang.org/protobuf/internal/editiondefaults"
	"google.golang.org/protobuf/internal/genid"
	"google.golang.org/protobuf/reflect/protoreflect"
)

var defaultsCache = make(map[Edition]EditionFeatures)
var defaultsKeys = []Edition{}

func init() {
	unmarshalEditionDefaults(editiondefaults.Defaults)
	SurrogateProto2.L1.EditionFeatures = getFeaturesFor(EditionProto2)
	SurrogateProto3.L1.EditionFeatures = getFeaturesFor(EditionProto3)
	SurrogateEdition2023.L1.EditionFeatures = getFeaturesFor(Edition2023)
}

func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures {
	for len(b) > 0 {
		num, _, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch num {
		case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
			v, m := protowire.ConsumeVarint(b)
			b = b[m:]
			parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v)
		default:
			panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num))
		}
	}
	return parent
}

func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures {
	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.VarintType:
			v, m := protowire.ConsumeVarint(b)
			b = b[m:]
			switch num {
			case genid.FeatureSet_FieldPresence_field_number:
				parent.IsFieldPresence = v == genid.FeatureSet_EXPLICIT_enum_value || v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
				parent.IsLegacyRequired = v == genid.FeatureSet_LEGACY_REQUIRED_enum_value
			case genid.FeatureSet_EnumType_field_number:
				parent.IsOpenEnum = v == genid.FeatureSet_OPEN_enum_value
			case genid.FeatureSet_RepeatedFieldEncoding_field_number:
				parent.IsPacked = v == genid.FeatureSet_PACKED_enum_value
			case genid.FeatureSet_Utf8Validation_field_number:
				parent.IsUTF8Validated = v == genid.FeatureSet_VERIFY_enum_value
			case genid.FeatureSet_MessageEncoding_field_number:
				parent.IsDelimitedEncoded = v == genid.FeatureSet_DELIMITED_enum_value
			case genid.FeatureSet_JsonFormat_field_number:
				parent.IsJSONCompliant = v == genid.FeatureSet_ALLOW_enum_value
			default:
				panic(fmt.Sprintf("unkown field number %d while unmarshalling FeatureSet", num))
			}
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number:
				parent = unmarshalGoFeature(v, parent)
			}
		}
	}

	return parent
}

func featuresFromParentDesc(parentDesc protoreflect.Descriptor) EditionFeatures {
	var parentFS EditionFeatures
	switch p := parentDesc.(type) {
	case *File:
		parentFS = p.L1.EditionFeatures
	case *Message:
		parentFS = p.L1.EditionFeatures
	default:
		panic(fmt.Sprintf("unknown parent type %T", parentDesc))
	}
	return parentFS
}

func unmarshalEditionDefault(b []byte) {
	var ed Edition
	var fs EditionFeatures
	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.VarintType:
			v, m := protowire.ConsumeVarint(b)
			b = b[m:]
			switch num {
			case genid.FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number:
				ed = Edition(v)
			}
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number:
				fs = unmarshalFeatureSet(v, fs)
			case genid.FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number:
				fs = unmarshalFeatureSet(v, fs)
			}
		}
	}
	defaultsCache[ed] = fs
	defaultsKeys = append(defaultsKeys, ed)
}

func unmarshalEditionDefaults(b []byte) {
	for len(b) > 0 {
		num, _, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch num {
		case genid.FeatureSetDefaults_Defaults_field_number:
			def, m := protowire.ConsumeBytes(b)
			b = b[m:]
			unmarshalEditionDefault(def)
		case genid.FeatureSetDefaults_MinimumEdition_field_number,
			genid.FeatureSetDefaults_MaximumEdition_field_number:
			// We don't care about the minimum and maximum editions. If the
			// edition we are looking for later on is not in the cache we know
			// it is outside of the range between minimum and maximum edition.
			_, m := protowire.ConsumeVarint(b)
			b = b[m:]
		default:
			panic(fmt.Sprintf("unkown field number %d while unmarshalling EditionDefault", num))
		}
	}
}

func getFeaturesFor(ed Edition) EditionFeatures {
	match := EditionUnknown
	for _, key := range defaultsKeys {
		if key > ed {
			break
		}
		match = key
	}
	if match == EditionUnknown {
		panic(fmt.Sprintf("unsupported edition: %v", ed))
	}
	return defaultsCache[match]
}
