// Code generated by "gen/generator.go"; DO NOT EDIT.
// In order to regenerate this file execute `go generate` from the repository root.
// More details can be found in the [README](https://github.com/CiscoDevNet/terraform-provider-aci/blob/master/README.md).

package provider

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/ciscoecosystem/aci-go-client/v2/client"
	"github.com/ciscoecosystem/aci-go-client/v2/container"
	"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
	"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
	"github.com/hashicorp/terraform-plugin-framework/attr"
	"github.com/hashicorp/terraform-plugin-framework/diag"
	"github.com/hashicorp/terraform-plugin-framework/path"
	"github.com/hashicorp/terraform-plugin-framework/resource"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
	"github.com/hashicorp/terraform-plugin-framework/types"
	"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
	"github.com/hashicorp/terraform-plugin-log/tflog"
)

// Ensure provider defined types fully satisfy framework interfaces.
var _ resource.Resource = &VzRsDenyRuleResource{}
var _ resource.ResourceWithImportState = &VzRsDenyRuleResource{}

func NewVzRsDenyRuleResource() resource.Resource {
	return &VzRsDenyRuleResource{}
}

// VzRsDenyRuleResource defines the resource implementation.
type VzRsDenyRuleResource struct {
	client *client.Client
}

// VzRsDenyRuleResourceModel describes the resource data model.
type VzRsDenyRuleResourceModel struct {
	Id             types.String `tfsdk:"id"`
	ParentDn       types.String `tfsdk:"parent_dn"`
	Annotation     types.String `tfsdk:"annotation"`
	Directives     types.Set    `tfsdk:"directives"`
	TnVzFilterName types.String `tfsdk:"filter_name"`
	TagAnnotation  types.Set    `tfsdk:"annotations"`
	TagTag         types.Set    `tfsdk:"tags"`
}

func getEmptyVzRsDenyRuleResourceModel() *VzRsDenyRuleResourceModel {
	return &VzRsDenyRuleResourceModel{
		Id:             basetypes.NewStringNull(),
		ParentDn:       basetypes.NewStringNull(),
		Annotation:     basetypes.NewStringNull(),
		Directives:     types.SetNull(types.StringType),
		TnVzFilterName: basetypes.NewStringNull(),
		TagAnnotation: types.SetNull(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"key":   types.StringType,
				"value": types.StringType,
			},
		}),
		TagTag: types.SetNull(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"key":   types.StringType,
				"value": types.StringType,
			},
		}),
	}
}

// TagAnnotationVzRsDenyRuleResourceModel describes the resource data model for the children without relation ships.
type TagAnnotationVzRsDenyRuleResourceModel struct {
	Key   types.String `tfsdk:"key"`
	Value types.String `tfsdk:"value"`
}

func getEmptyTagAnnotationVzRsDenyRuleResourceModel() TagAnnotationVzRsDenyRuleResourceModel {
	return TagAnnotationVzRsDenyRuleResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

var TagAnnotationVzRsDenyRuleType = types.ObjectType{
	AttrTypes: map[string]attr.Type{
		"key":   types.StringType,
		"value": types.StringType,
	},
}

// TagTagVzRsDenyRuleResourceModel describes the resource data model for the children without relation ships.
type TagTagVzRsDenyRuleResourceModel struct {
	Key   types.String `tfsdk:"key"`
	Value types.String `tfsdk:"value"`
}

func getEmptyTagTagVzRsDenyRuleResourceModel() TagTagVzRsDenyRuleResourceModel {
	return TagTagVzRsDenyRuleResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

var TagTagVzRsDenyRuleType = types.ObjectType{
	AttrTypes: map[string]attr.Type{
		"key":   types.StringType,
		"value": types.StringType,
	},
}

type VzRsDenyRuleIdentifier struct {
	TnVzFilterName types.String
}

func (r *VzRsDenyRuleResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
	if !req.Plan.Raw.IsNull() {
		var planData, stateData *VzRsDenyRuleResourceModel
		resp.Diagnostics.Append(req.Plan.Get(ctx, &planData)...)
		resp.Diagnostics.Append(req.State.Get(ctx, &stateData)...)

		if resp.Diagnostics.HasError() {
			return
		}

		if (planData.Id.IsUnknown() || planData.Id.IsNull()) && !planData.ParentDn.IsUnknown() && !planData.TnVzFilterName.IsUnknown() {
			setVzRsDenyRuleId(ctx, planData)
		}

		if stateData == nil && !globalAllowExistingOnCreate && !planData.Id.IsUnknown() && !planData.Id.IsNull() {
			CheckDn(ctx, &resp.Diagnostics, r.client, "vzRsDenyRule", planData.Id.ValueString())
			if resp.Diagnostics.HasError() {
				return
			}
		}

		resp.Diagnostics.Append(resp.Plan.Set(ctx, &planData)...)
	}
}

func (r *VzRsDenyRuleResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
	tflog.Debug(ctx, "Start metadata of resource: aci_relation_from_taboo_contract_subject_to_filter")
	resp.TypeName = req.ProviderTypeName + "_relation_from_taboo_contract_subject_to_filter"
	tflog.Debug(ctx, "End metadata of resource: aci_relation_from_taboo_contract_subject_to_filter")
}

func (r *VzRsDenyRuleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
	tflog.Debug(ctx, "Start schema of resource: aci_relation_from_taboo_contract_subject_to_filter")
	resp.Schema = schema.Schema{
		// This description is used by the documentation generator and the language server.
		MarkdownDescription: "The relation_from_taboo_contract_subject_to_filter resource for the 'vzRsDenyRule' class",

		Attributes: map[string]schema.Attribute{
			"id": schema.StringAttribute{
				Computed:            true,
				MarkdownDescription: "The distinguished name (DN) of the Relation From Taboo Contract Subject To Filter object.",
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
				},
			},
			"parent_dn": schema.StringAttribute{
				Required:            true,
				MarkdownDescription: "The distinguished name (DN) of the parent object.",
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					stringplanmodifier.RequiresReplace(),
				},
			},
			"annotation": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				Default:             stringdefault.StaticString(globalAnnotation),
				MarkdownDescription: `The annotation of the Relation From Taboo Contract Subject To Filter object.`,
			},
			"directives": schema.SetAttribute{
				MarkdownDescription: `The directives of the Relation From Taboo Contract Subject To Filter object. Use the 'no_stats' option for Policy Compression, which allows for the utilization of fewer TCAM resources. Use the 'log' option to log packets and provide information about traffic that is hitting the rule of interest. See the [contract configuration options](https://www.cisco.com/c/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/white-paper-c11-743951.html#Contractconfigurationoptions) in the Cisco ACI Contract Guide White Paper for more information.`,
				Optional:            true,
				Computed:            true,
				PlanModifiers: []planmodifier.Set{
					setplanmodifier.UseStateForUnknown(),
					SetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate(nil),
				},
				Validators: []validator.Set{
					setvalidator.SizeAtMost(2),
					setvalidator.ValueStringsAre(
						stringvalidator.OneOf("log", "no_stats"),
					),
				},
				ElementType: types.StringType,
			},
			"filter_name": schema.StringAttribute{
				Required: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
					stringplanmodifier.RequiresReplace(),
				},
				MarkdownDescription: `The name of the filter object.`,
			},
			"annotations": schema.SetNestedAttribute{
				MarkdownDescription: ``,
				Optional:            true,
				Computed:            true,
				PlanModifiers: []planmodifier.Set{
					setplanmodifier.UseStateForUnknown(),
				},
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{
						"key": schema.StringAttribute{
							Required: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The key used to uniquely identify this configuration object.`,
						},
						"value": schema.StringAttribute{
							Required: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The value of the property.`,
						},
					},
				},
			},
			"tags": schema.SetNestedAttribute{
				MarkdownDescription: ``,
				Optional:            true,
				Computed:            true,
				PlanModifiers: []planmodifier.Set{
					setplanmodifier.UseStateForUnknown(),
				},
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{
						"key": schema.StringAttribute{
							Required: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The key used to uniquely identify this configuration object.`,
						},
						"value": schema.StringAttribute{
							Required: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The value of the property.`,
						},
					},
				},
			},
		},
	}
	tflog.Debug(ctx, "End schema of resource: aci_relation_from_taboo_contract_subject_to_filter")
}

func (r *VzRsDenyRuleResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
	tflog.Debug(ctx, "Start configure of resource: aci_relation_from_taboo_contract_subject_to_filter")
	// Prevent panic if the provider has not been configured.
	if req.ProviderData == nil {
		return
	}

	client, ok := req.ProviderData.(*client.Client)

	if !ok {
		resp.Diagnostics.AddError(
			"Unexpected Resource Configure Type",
			fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
		)

		return
	}

	r.client = client
	tflog.Debug(ctx, "End configure of resource: aci_relation_from_taboo_contract_subject_to_filter")
}

func (r *VzRsDenyRuleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
	tflog.Debug(ctx, "Start create of resource: aci_relation_from_taboo_contract_subject_to_filter")
	// On create retrieve information on current state prior to making any changes in order to determine child delete operations
	var stateData *VzRsDenyRuleResourceModel
	resp.Diagnostics.Append(req.Plan.Get(ctx, &stateData)...)
	if stateData.Id.IsUnknown() || stateData.Id.IsNull() {
		setVzRsDenyRuleId(ctx, stateData)
	}
	getAndSetVzRsDenyRuleAttributes(ctx, &resp.Diagnostics, r.client, stateData)
	if !globalAllowExistingOnCreate && !stateData.Id.IsNull() {
		resp.Diagnostics.AddError(
			"Object Already Exists",
			fmt.Sprintf("The vzRsDenyRule object with DN '%s' already exists.", stateData.Id.ValueString()),
		)
		return
	}

	var data *VzRsDenyRuleResourceModel

	// Read Terraform plan data into the model
	resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

	if resp.Diagnostics.HasError() {
		return
	}

	if data.Id.IsUnknown() || data.Id.IsNull() {
		setVzRsDenyRuleId(ctx, data)
	}

	tflog.Debug(ctx, fmt.Sprintf("Create of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))

	var tagAnnotationPlan, tagAnnotationState []TagAnnotationVzRsDenyRuleResourceModel
	data.TagAnnotation.ElementsAs(ctx, &tagAnnotationPlan, false)
	stateData.TagAnnotation.ElementsAs(ctx, &tagAnnotationState, false)
	var tagTagPlan, tagTagState []TagTagVzRsDenyRuleResourceModel
	data.TagTag.ElementsAs(ctx, &tagTagPlan, false)
	stateData.TagTag.ElementsAs(ctx, &tagTagState, false)
	jsonPayload := getVzRsDenyRuleCreateJsonPayload(ctx, &resp.Diagnostics, true, data, tagAnnotationPlan, tagAnnotationState, tagTagPlan, tagTagState)

	if resp.Diagnostics.HasError() {
		return
	}

	DoRestRequest(ctx, &resp.Diagnostics, r.client, fmt.Sprintf("api/mo/%s.json", data.Id.ValueString()), "POST", jsonPayload)

	if resp.Diagnostics.HasError() {
		return
	}

	getAndSetVzRsDenyRuleAttributes(ctx, &resp.Diagnostics, r.client, data)

	// Save data into Terraform state
	resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
	tflog.Debug(ctx, fmt.Sprintf("End create of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))
}

func (r *VzRsDenyRuleResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
	tflog.Debug(ctx, "Start read of resource: aci_relation_from_taboo_contract_subject_to_filter")
	var data *VzRsDenyRuleResourceModel

	// Read Terraform prior state data into the model
	resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

	if resp.Diagnostics.HasError() {
		return
	}

	tflog.Debug(ctx, fmt.Sprintf("Read of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))

	getAndSetVzRsDenyRuleAttributes(ctx, &resp.Diagnostics, r.client, data)

	// Save updated data into Terraform state
	if data.Id.IsNull() {
		var emptyData *VzRsDenyRuleResourceModel
		resp.Diagnostics.Append(resp.State.Set(ctx, &emptyData)...)
	} else {
		resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
	}

	tflog.Debug(ctx, fmt.Sprintf("End read of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))
}

func (r *VzRsDenyRuleResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
	tflog.Debug(ctx, "Start update of resource: aci_relation_from_taboo_contract_subject_to_filter")
	var data *VzRsDenyRuleResourceModel
	var stateData *VzRsDenyRuleResourceModel

	// Read Terraform plan data into the model
	resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
	resp.Diagnostics.Append(req.State.Get(ctx, &stateData)...)

	if resp.Diagnostics.HasError() {
		return
	}

	tflog.Debug(ctx, fmt.Sprintf("Update of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))

	var tagAnnotationPlan, tagAnnotationState []TagAnnotationVzRsDenyRuleResourceModel
	data.TagAnnotation.ElementsAs(ctx, &tagAnnotationPlan, false)
	stateData.TagAnnotation.ElementsAs(ctx, &tagAnnotationState, false)
	var tagTagPlan, tagTagState []TagTagVzRsDenyRuleResourceModel
	data.TagTag.ElementsAs(ctx, &tagTagPlan, false)
	stateData.TagTag.ElementsAs(ctx, &tagTagState, false)
	jsonPayload := getVzRsDenyRuleCreateJsonPayload(ctx, &resp.Diagnostics, false, data, tagAnnotationPlan, tagAnnotationState, tagTagPlan, tagTagState)

	if resp.Diagnostics.HasError() {
		return
	}

	DoRestRequest(ctx, &resp.Diagnostics, r.client, fmt.Sprintf("api/mo/%s.json", data.Id.ValueString()), "POST", jsonPayload)

	if resp.Diagnostics.HasError() {
		return
	}

	getAndSetVzRsDenyRuleAttributes(ctx, &resp.Diagnostics, r.client, data)

	// Save updated data into Terraform state
	resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
	tflog.Debug(ctx, fmt.Sprintf("End update of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))
}

func (r *VzRsDenyRuleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
	tflog.Debug(ctx, "Start delete of resource: aci_relation_from_taboo_contract_subject_to_filter")
	var data *VzRsDenyRuleResourceModel

	// Read Terraform prior state data into the model
	resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

	if resp.Diagnostics.HasError() {
		return
	}

	tflog.Debug(ctx, fmt.Sprintf("Delete of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))
	jsonPayload := GetDeleteJsonPayload(ctx, &resp.Diagnostics, "vzRsDenyRule", data.Id.ValueString())
	if resp.Diagnostics.HasError() {
		return
	}
	DoRestRequest(ctx, &resp.Diagnostics, r.client, fmt.Sprintf("api/mo/%s.json", data.Id.ValueString()), "POST", jsonPayload)
	if resp.Diagnostics.HasError() {
		return
	}
	tflog.Debug(ctx, fmt.Sprintf("End delete of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", data.Id.ValueString()))
}

func (r *VzRsDenyRuleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
	tflog.Debug(ctx, "Start import state of resource: aci_relation_from_taboo_contract_subject_to_filter")
	resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)

	var stateData *VzRsDenyRuleResourceModel
	resp.Diagnostics.Append(resp.State.Get(ctx, &stateData)...)
	tflog.Debug(ctx, fmt.Sprintf("Import state of resource aci_relation_from_taboo_contract_subject_to_filter with id '%s'", stateData.Id.ValueString()))

	tflog.Debug(ctx, "End import of state resource: aci_relation_from_taboo_contract_subject_to_filter")
}

func getAndSetVzRsDenyRuleAttributes(ctx context.Context, diags *diag.Diagnostics, client *client.Client, data *VzRsDenyRuleResourceModel) {
	requestData := DoRestRequest(ctx, diags, client, fmt.Sprintf("api/mo/%s.json?rsp-subtree=full&rsp-subtree-class=%s", data.Id.ValueString(), "vzRsDenyRule,tagAnnotation,tagTag"), "GET", nil)

	readData := getEmptyVzRsDenyRuleResourceModel()

	if diags.HasError() {
		return
	}
	if requestData.Search("imdata").Search("vzRsDenyRule").Data() != nil {
		classReadInfo := requestData.Search("imdata").Search("vzRsDenyRule").Data().([]interface{})
		if len(classReadInfo) == 1 {
			attributes := classReadInfo[0].(map[string]interface{})["attributes"].(map[string]interface{})
			for attributeName, attributeValue := range attributes {
				if attributeName == "dn" {
					readData.Id = basetypes.NewStringValue(attributeValue.(string))
					setVzRsDenyRuleParentDn(ctx, attributeValue.(string), readData)
				}
				if attributeName == "annotation" {
					readData.Annotation = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "directives" {
					directivesList := make([]string, 0)
					if attributeValue.(string) != "" {
						directivesList = strings.Split(attributeValue.(string), ",")
					}
					directivesSet, _ := types.SetValueFrom(ctx, readData.Directives.ElementType(ctx), directivesList)
					readData.Directives = directivesSet
				}
				if attributeName == "tnVzFilterName" {
					readData.TnVzFilterName = basetypes.NewStringValue(attributeValue.(string))
				}
			}
			TagAnnotationVzRsDenyRuleList := make([]TagAnnotationVzRsDenyRuleResourceModel, 0)
			TagTagVzRsDenyRuleList := make([]TagTagVzRsDenyRuleResourceModel, 0)
			_, ok := classReadInfo[0].(map[string]interface{})["children"]
			if ok {
				children := classReadInfo[0].(map[string]interface{})["children"].([]interface{})
				for _, child := range children {
					for childClassName, childClassDetails := range child.(map[string]interface{}) {
						childAttributes := childClassDetails.(map[string]interface{})["attributes"].(map[string]interface{})
						if childClassName == "tagAnnotation" {
							TagAnnotationVzRsDenyRule := getEmptyTagAnnotationVzRsDenyRuleResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "key" {
									TagAnnotationVzRsDenyRule.Key = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "value" {
									TagAnnotationVzRsDenyRule.Value = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagAnnotationVzRsDenyRuleList = append(TagAnnotationVzRsDenyRuleList, TagAnnotationVzRsDenyRule)
						}
						if childClassName == "tagTag" {
							TagTagVzRsDenyRule := getEmptyTagTagVzRsDenyRuleResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "key" {
									TagTagVzRsDenyRule.Key = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "value" {
									TagTagVzRsDenyRule.Value = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagTagVzRsDenyRuleList = append(TagTagVzRsDenyRuleList, TagTagVzRsDenyRule)
						}
					}
				}
			}
			tagAnnotationSet, _ := types.SetValueFrom(ctx, readData.TagAnnotation.ElementType(ctx), TagAnnotationVzRsDenyRuleList)
			readData.TagAnnotation = tagAnnotationSet
			tagTagSet, _ := types.SetValueFrom(ctx, readData.TagTag.ElementType(ctx), TagTagVzRsDenyRuleList)
			readData.TagTag = tagTagSet
		} else {
			diags.AddError(
				"too many results in response",
				fmt.Sprintf("%v matches returned for class 'vzRsDenyRule'. Please report this issue to the provider developers.", len(classReadInfo)),
			)
		}
	} else {
		readData.Id = basetypes.NewStringNull()
	}
	*data = *readData
}

func getVzRsDenyRuleRn(ctx context.Context, data *VzRsDenyRuleResourceModel) string {
	return fmt.Sprintf("rsdenyRule-%s", data.TnVzFilterName.ValueString())
}

func setVzRsDenyRuleParentDn(ctx context.Context, dn string, data *VzRsDenyRuleResourceModel) {
	bracketIndex := 0
	rnIndex := 0
	for i := len(dn) - 1; i >= 0; i-- {
		if string(dn[i]) == "]" {
			bracketIndex = bracketIndex + 1
		} else if string(dn[i]) == "[" {
			bracketIndex = bracketIndex - 1
		} else if string(dn[i]) == "/" && bracketIndex == 0 {
			rnIndex = i
			break
		}
	}
	data.ParentDn = basetypes.NewStringValue(dn[:rnIndex])
}

func setVzRsDenyRuleId(ctx context.Context, data *VzRsDenyRuleResourceModel) {
	rn := getVzRsDenyRuleRn(ctx, data)
	data.Id = types.StringValue(fmt.Sprintf("%s/%s", data.ParentDn.ValueString(), rn))
}

func getVzRsDenyRuleTagAnnotationChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *VzRsDenyRuleResourceModel, tagAnnotationVzRsDenyRulePlan, tagAnnotationVzRsDenyRuleState []TagAnnotationVzRsDenyRuleResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.TagAnnotation.IsNull() && !data.TagAnnotation.IsUnknown() {
		tagAnnotationIdentifiers := []TagAnnotationIdentifier{}
		for _, tagAnnotationVzRsDenyRule := range tagAnnotationVzRsDenyRulePlan {
			childMap := NewAciObject()
			if !tagAnnotationVzRsDenyRule.Key.IsNull() && !tagAnnotationVzRsDenyRule.Key.IsUnknown() {
				childMap.Attributes["key"] = tagAnnotationVzRsDenyRule.Key.ValueString()
			}
			if !tagAnnotationVzRsDenyRule.Value.IsNull() && !tagAnnotationVzRsDenyRule.Value.IsUnknown() {
				childMap.Attributes["value"] = tagAnnotationVzRsDenyRule.Value.ValueString()
			}
			childPayloads = append(childPayloads, map[string]interface{}{"tagAnnotation": childMap})
			tagAnnotationIdentifier := TagAnnotationIdentifier{}
			tagAnnotationIdentifier.Key = tagAnnotationVzRsDenyRule.Key
			tagAnnotationIdentifiers = append(tagAnnotationIdentifiers, tagAnnotationIdentifier)
		}
		for _, tagAnnotation := range tagAnnotationVzRsDenyRuleState {
			delete := true
			for _, tagAnnotationIdentifier := range tagAnnotationIdentifiers {
				if tagAnnotationIdentifier.Key == tagAnnotation.Key {
					delete = false
					break
				}
			}
			if delete {
				tagAnnotationChildMapForDelete := NewAciObject()
				tagAnnotationChildMapForDelete.Attributes["status"] = "deleted"
				tagAnnotationChildMapForDelete.Attributes["key"] = tagAnnotation.Key.ValueString()
				childPayloads = append(childPayloads, map[string]interface{}{"tagAnnotation": tagAnnotationChildMapForDelete})
			}
		}
	} else {
		data.TagAnnotation = types.SetNull(data.TagAnnotation.ElementType(ctx))
	}

	return childPayloads
}

func getVzRsDenyRuleTagTagChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *VzRsDenyRuleResourceModel, tagTagVzRsDenyRulePlan, tagTagVzRsDenyRuleState []TagTagVzRsDenyRuleResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.TagTag.IsNull() && !data.TagTag.IsUnknown() {
		tagTagIdentifiers := []TagTagIdentifier{}
		for _, tagTagVzRsDenyRule := range tagTagVzRsDenyRulePlan {
			childMap := NewAciObject()
			if !tagTagVzRsDenyRule.Key.IsNull() && !tagTagVzRsDenyRule.Key.IsUnknown() {
				childMap.Attributes["key"] = tagTagVzRsDenyRule.Key.ValueString()
			}
			if !tagTagVzRsDenyRule.Value.IsNull() && !tagTagVzRsDenyRule.Value.IsUnknown() {
				childMap.Attributes["value"] = tagTagVzRsDenyRule.Value.ValueString()
			}
			childPayloads = append(childPayloads, map[string]interface{}{"tagTag": childMap})
			tagTagIdentifier := TagTagIdentifier{}
			tagTagIdentifier.Key = tagTagVzRsDenyRule.Key
			tagTagIdentifiers = append(tagTagIdentifiers, tagTagIdentifier)
		}
		for _, tagTag := range tagTagVzRsDenyRuleState {
			delete := true
			for _, tagTagIdentifier := range tagTagIdentifiers {
				if tagTagIdentifier.Key == tagTag.Key {
					delete = false
					break
				}
			}
			if delete {
				tagTagChildMapForDelete := NewAciObject()
				tagTagChildMapForDelete.Attributes["status"] = "deleted"
				tagTagChildMapForDelete.Attributes["key"] = tagTag.Key.ValueString()
				childPayloads = append(childPayloads, map[string]interface{}{"tagTag": tagTagChildMapForDelete})
			}
		}
	} else {
		data.TagTag = types.SetNull(data.TagTag.ElementType(ctx))
	}

	return childPayloads
}

func getVzRsDenyRuleCreateJsonPayload(ctx context.Context, diags *diag.Diagnostics, createType bool, data *VzRsDenyRuleResourceModel, tagAnnotationPlan, tagAnnotationState []TagAnnotationVzRsDenyRuleResourceModel, tagTagPlan, tagTagState []TagTagVzRsDenyRuleResourceModel) *container.Container {
	payloadMap := map[string]interface{}{}
	payloadMap["attributes"] = map[string]string{}

	if createType && !globalAllowExistingOnCreate {
		payloadMap["attributes"].(map[string]string)["status"] = "created"
	}
	childPayloads := []map[string]interface{}{}

	TagAnnotationchildPayloads := getVzRsDenyRuleTagAnnotationChildPayloads(ctx, diags, data, tagAnnotationPlan, tagAnnotationState)
	if TagAnnotationchildPayloads == nil {
		return nil
	}
	childPayloads = append(childPayloads, TagAnnotationchildPayloads...)

	TagTagchildPayloads := getVzRsDenyRuleTagTagChildPayloads(ctx, diags, data, tagTagPlan, tagTagState)
	if TagTagchildPayloads == nil {
		return nil
	}
	childPayloads = append(childPayloads, TagTagchildPayloads...)

	payloadMap["children"] = childPayloads
	if !data.Annotation.IsNull() && !data.Annotation.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["annotation"] = data.Annotation.ValueString()
	}
	if !data.Directives.IsNull() && !data.Directives.IsUnknown() {
		var tmpDirectives []string
		data.Directives.ElementsAs(ctx, &tmpDirectives, false)
		payloadMap["attributes"].(map[string]string)["directives"] = strings.Join(tmpDirectives, ",")
	}
	if !data.TnVzFilterName.IsNull() && !data.TnVzFilterName.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["tnVzFilterName"] = data.TnVzFilterName.ValueString()
	}
	payload, err := json.Marshal(map[string]interface{}{"vzRsDenyRule": payloadMap})
	if err != nil {
		diags.AddError(
			"Marshalling of json payload failed",
			fmt.Sprintf("Err: %s. Please report this issue to the provider developers.", err),
		)
		return nil
	}

	jsonPayload, err := container.ParseJSON(payload)

	if err != nil {
		diags.AddError(
			"Construction of json payload failed",
			fmt.Sprintf("Err: %s. Please report this issue to the provider developers.", err),
		)
		return nil
	}
	return jsonPayload
}
