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

	"github.com/ciscoecosystem/aci-go-client/v2/client"
	"github.com/ciscoecosystem/aci-go-client/v2/container"
	"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/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 = &FvSiteAssociatedResource{}
var _ resource.ResourceWithImportState = &FvSiteAssociatedResource{}

func NewFvSiteAssociatedResource() resource.Resource {
	return &FvSiteAssociatedResource{}
}

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

// FvSiteAssociatedResourceModel describes the resource data model.
type FvSiteAssociatedResourceModel struct {
	Id            types.String `tfsdk:"id"`
	ParentDn      types.String `tfsdk:"parent_dn"`
	Annotation    types.String `tfsdk:"annotation"`
	Descr         types.String `tfsdk:"description"`
	Name          types.String `tfsdk:"name"`
	NameAlias     types.String `tfsdk:"name_alias"`
	OwnerKey      types.String `tfsdk:"owner_key"`
	OwnerTag      types.String `tfsdk:"owner_tag"`
	SiteId        types.String `tfsdk:"site_id"`
	FvRemoteId    types.Set    `tfsdk:"remote_sites"`
	TagAnnotation types.Set    `tfsdk:"annotations"`
	TagTag        types.Set    `tfsdk:"tags"`
}

func getEmptyFvSiteAssociatedResourceModel() *FvSiteAssociatedResourceModel {
	return &FvSiteAssociatedResourceModel{
		Id:         basetypes.NewStringNull(),
		ParentDn:   basetypes.NewStringNull(),
		Annotation: basetypes.NewStringNull(),
		Descr:      basetypes.NewStringNull(),
		Name:       basetypes.NewStringNull(),
		NameAlias:  basetypes.NewStringNull(),
		OwnerKey:   basetypes.NewStringNull(),
		OwnerTag:   basetypes.NewStringNull(),
		SiteId:     basetypes.NewStringNull(),
		FvRemoteId: types.SetNull(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"annotation":        types.StringType,
				"description":       types.StringType,
				"name":              types.StringType,
				"name_alias":        types.StringType,
				"owner_key":         types.StringType,
				"owner_tag":         types.StringType,
				"remote_vrf_pc_tag": types.StringType,
				"remote_pc_tag":     types.StringType,
				"site_id":           types.StringType,
				"annotations":       types.SetType{ElemType: TagAnnotationFvRemoteIdFvSiteAssociatedType},
				"tags":              types.SetType{ElemType: TagTagFvRemoteIdFvSiteAssociatedType},
			},
		}),
		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,
			},
		}),
	}
}

// FvRemoteIdFvSiteAssociatedResourceModel describes the resource data model for the children without relation ships.
type FvRemoteIdFvSiteAssociatedResourceModel struct {
	Annotation     types.String `tfsdk:"annotation"`
	Descr          types.String `tfsdk:"description"`
	Name           types.String `tfsdk:"name"`
	NameAlias      types.String `tfsdk:"name_alias"`
	OwnerKey       types.String `tfsdk:"owner_key"`
	OwnerTag       types.String `tfsdk:"owner_tag"`
	RemoteCtxPcTag types.String `tfsdk:"remote_vrf_pc_tag"`
	RemotePcTag    types.String `tfsdk:"remote_pc_tag"`
	SiteId         types.String `tfsdk:"site_id"`
	TagAnnotation  types.Set    `tfsdk:"annotations"`
	TagTag         types.Set    `tfsdk:"tags"`
}

func getEmptyFvRemoteIdFvSiteAssociatedResourceModel() FvRemoteIdFvSiteAssociatedResourceModel {
	return FvRemoteIdFvSiteAssociatedResourceModel{
		Annotation:     basetypes.NewStringNull(),
		Descr:          basetypes.NewStringNull(),
		Name:           basetypes.NewStringNull(),
		NameAlias:      basetypes.NewStringNull(),
		OwnerKey:       basetypes.NewStringNull(),
		OwnerTag:       basetypes.NewStringNull(),
		RemoteCtxPcTag: basetypes.NewStringNull(),
		RemotePcTag:    basetypes.NewStringNull(),
		SiteId:         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,
			},
		}),
	}
}

var FvRemoteIdFvSiteAssociatedType = types.ObjectType{
	AttrTypes: map[string]attr.Type{
		"annotation":        types.StringType,
		"description":       types.StringType,
		"name":              types.StringType,
		"name_alias":        types.StringType,
		"owner_key":         types.StringType,
		"owner_tag":         types.StringType,
		"remote_vrf_pc_tag": types.StringType,
		"remote_pc_tag":     types.StringType,
		"site_id":           types.StringType,
		"annotations":       types.SetType{ElemType: TagAnnotationFvRemoteIdFvSiteAssociatedType},
		"tags":              types.SetType{ElemType: TagTagFvRemoteIdFvSiteAssociatedType},
	},
}

func FvRemoteIdFvSiteAssociatedSetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate(ctx context.Context, planValue, stateValue types.Set) basetypes.SetValue {
	//  Function is needed to handle the case that an attribute is not yet supported in a version and gets set to null during read
	var planSetValues, stateSetValues []FvRemoteIdFvSiteAssociatedResourceModel
	stateValue.ElementsAs(ctx, &stateSetValues, false)
	planValue.ElementsAs(ctx, &planSetValues, false)

	// If the length of the state and plan values are different a change is already detected the loop can be skipped
	if len(stateSetValues) == len(planSetValues) {
		for index, stateValue := range stateSetValues {
			nullInStateFound := false
			if stateValue.Annotation.IsNull() {
				nullInStateFound = true
				planSetValues[index].Annotation = basetypes.NewStringNull()
			}
			if stateValue.Descr.IsNull() {
				nullInStateFound = true
				planSetValues[index].Descr = basetypes.NewStringNull()
			}
			if stateValue.Name.IsNull() {
				nullInStateFound = true
				planSetValues[index].Name = basetypes.NewStringNull()
			}
			if stateValue.NameAlias.IsNull() {
				nullInStateFound = true
				planSetValues[index].NameAlias = basetypes.NewStringNull()
			}
			if stateValue.OwnerKey.IsNull() {
				nullInStateFound = true
				planSetValues[index].OwnerKey = basetypes.NewStringNull()
			}
			if stateValue.OwnerTag.IsNull() {
				nullInStateFound = true
				planSetValues[index].OwnerTag = basetypes.NewStringNull()
			}
			if stateValue.RemoteCtxPcTag.IsNull() {
				nullInStateFound = true
				planSetValues[index].RemoteCtxPcTag = basetypes.NewStringNull()
			}
			if stateValue.RemotePcTag.IsNull() {
				nullInStateFound = true
				planSetValues[index].RemotePcTag = basetypes.NewStringNull()
			}
			if stateValue.SiteId.IsNull() {
				nullInStateFound = true
				planSetValues[index].SiteId = basetypes.NewStringNull()
			}
			if !nullInStateFound {
				// when there are no null fields we can conclude the version supports all attributes in set
				break
			}
		}
	}
	planSet, _ := types.SetValueFrom(ctx, FvRemoteIdFvSiteAssociatedType, planSetValues)
	return planSet

}

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

func getEmptyTagAnnotationFvRemoteIdFvSiteAssociatedResourceModel() TagAnnotationFvRemoteIdFvSiteAssociatedResourceModel {
	return TagAnnotationFvRemoteIdFvSiteAssociatedResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

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

func getEmptyTagTagFvRemoteIdFvSiteAssociatedResourceModel() TagTagFvRemoteIdFvSiteAssociatedResourceModel {
	return TagTagFvRemoteIdFvSiteAssociatedResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

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

func getEmptyTagAnnotationFvSiteAssociatedResourceModel() TagAnnotationFvSiteAssociatedResourceModel {
	return TagAnnotationFvSiteAssociatedResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

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

func getEmptyTagTagFvSiteAssociatedResourceModel() TagTagFvSiteAssociatedResourceModel {
	return TagTagFvSiteAssociatedResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

func (r *FvSiteAssociatedResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
	if !req.Plan.Raw.IsNull() {
		var planData, stateData *FvSiteAssociatedResourceModel
		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() {
			setFvSiteAssociatedId(ctx, planData)
		}

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

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

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

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

		Attributes: map[string]schema.Attribute{
			"id": schema.StringAttribute{
				Computed:            true,
				MarkdownDescription: "The distinguished name (DN) of the Associated Site 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 Associated Site object.`,
			},
			"description": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The description of the Associated Site object.`,
			},
			"name": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The name of the Associated Site object.`,
			},
			"name_alias": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The name alias of the Associated Site object.`,
			},
			"owner_key": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The key for enabling clients to own their data for entity correlation.`,
			},
			"owner_tag": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `A tag for enabling clients to add their own data. For example, to indicate who created this object.`,
			},
			"site_id": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The primary/local site identifier associated with the object as an integer.`,
			},
			"remote_sites": schema.SetNestedAttribute{
				MarkdownDescription: ``,
				Optional:            true,
				Computed:            true,
				PlanModifiers: []planmodifier.Set{
					setplanmodifier.UseStateForUnknown(),
					SetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate(FvRemoteIdFvSiteAssociatedSetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate),
				},
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{
						"annotation": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The annotation of the Remote Site object.`,
						},
						"description": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The description of the Remote Site object.`,
						},
						"name": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The name of the Remote Site object.`,
						},
						"name_alias": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The name alias of the Remote Site object.`,
						},
						"owner_key": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The key for enabling clients to own their data for entity correlation.`,
						},
						"owner_tag": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `A tag for enabling clients to add their own data. For example, to indicate who created this object.`,
						},
						"remote_vrf_pc_tag": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The policy class tag (pcTag) of the remote VRF. This attribute can only be present when the object for site association is a VRF.`,
						},
						"remote_pc_tag": schema.StringAttribute{
							Optional: true,
							Computed: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The policy class tag (pcTag) of the remote object.`,
						},
						"site_id": schema.StringAttribute{
							Required: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							MarkdownDescription: `The remote site identifier that is associated with the object of the primary/local site as an integer.`,
						},
						"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.`,
									},
								},
							},
						},
					},
				},
			},
			"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_associated_site")
}

func (r *FvSiteAssociatedResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
	tflog.Debug(ctx, "Start configure of resource: aci_associated_site")
	// 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_associated_site")
}

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

	var data *FvSiteAssociatedResourceModel

	// 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() {
		setFvSiteAssociatedId(ctx, data)
	}

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

	var fvRemoteIdPlan, fvRemoteIdState []FvRemoteIdFvSiteAssociatedResourceModel
	data.FvRemoteId.ElementsAs(ctx, &fvRemoteIdPlan, false)
	stateData.FvRemoteId.ElementsAs(ctx, &fvRemoteIdState, false)
	var tagAnnotationPlan, tagAnnotationState []TagAnnotationFvSiteAssociatedResourceModel
	data.TagAnnotation.ElementsAs(ctx, &tagAnnotationPlan, false)
	stateData.TagAnnotation.ElementsAs(ctx, &tagAnnotationState, false)
	var tagTagPlan, tagTagState []TagTagFvSiteAssociatedResourceModel
	data.TagTag.ElementsAs(ctx, &tagTagPlan, false)
	stateData.TagTag.ElementsAs(ctx, &tagTagState, false)
	jsonPayload := getFvSiteAssociatedCreateJsonPayload(ctx, &resp.Diagnostics, true, data, fvRemoteIdPlan, fvRemoteIdState, 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
	}

	getAndSetFvSiteAssociatedAttributes(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_associated_site with id '%s'", data.Id.ValueString()))
}

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

	// 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_associated_site with id '%s'", data.Id.ValueString()))

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

	// Save updated data into Terraform state
	if data.Id.IsNull() {
		var emptyData *FvSiteAssociatedResourceModel
		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_associated_site with id '%s'", data.Id.ValueString()))
}

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

	// 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_associated_site with id '%s'", data.Id.ValueString()))

	var fvRemoteIdPlan, fvRemoteIdState []FvRemoteIdFvSiteAssociatedResourceModel
	data.FvRemoteId.ElementsAs(ctx, &fvRemoteIdPlan, false)
	stateData.FvRemoteId.ElementsAs(ctx, &fvRemoteIdState, false)
	var tagAnnotationPlan, tagAnnotationState []TagAnnotationFvSiteAssociatedResourceModel
	data.TagAnnotation.ElementsAs(ctx, &tagAnnotationPlan, false)
	stateData.TagAnnotation.ElementsAs(ctx, &tagAnnotationState, false)
	var tagTagPlan, tagTagState []TagTagFvSiteAssociatedResourceModel
	data.TagTag.ElementsAs(ctx, &tagTagPlan, false)
	stateData.TagTag.ElementsAs(ctx, &tagTagState, false)
	jsonPayload := getFvSiteAssociatedCreateJsonPayload(ctx, &resp.Diagnostics, false, data, fvRemoteIdPlan, fvRemoteIdState, 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
	}

	getAndSetFvSiteAssociatedAttributes(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_associated_site with id '%s'", data.Id.ValueString()))
}

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

	// 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_associated_site with id '%s'", data.Id.ValueString()))
	jsonPayload := GetDeleteJsonPayload(ctx, &resp.Diagnostics, "fvSiteAssociated", 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_associated_site with id '%s'", data.Id.ValueString()))
}

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

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

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

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

	readData := getEmptyFvSiteAssociatedResourceModel()

	if diags.HasError() {
		return
	}
	if requestData.Search("imdata").Search("fvSiteAssociated").Data() != nil {
		classReadInfo := requestData.Search("imdata").Search("fvSiteAssociated").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))
					setFvSiteAssociatedParentDn(ctx, attributeValue.(string), readData)
				}
				if attributeName == "annotation" {
					readData.Annotation = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "descr" {
					readData.Descr = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "name" {
					readData.Name = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "nameAlias" {
					readData.NameAlias = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "ownerKey" {
					readData.OwnerKey = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "ownerTag" {
					readData.OwnerTag = basetypes.NewStringValue(attributeValue.(string))
				}
				if attributeName == "siteId" {
					readData.SiteId = basetypes.NewStringValue(attributeValue.(string))
				}
			}
			FvRemoteIdFvSiteAssociatedList := make([]FvRemoteIdFvSiteAssociatedResourceModel, 0)
			TagAnnotationFvSiteAssociatedList := make([]TagAnnotationFvSiteAssociatedResourceModel, 0)
			TagTagFvSiteAssociatedList := make([]TagTagFvSiteAssociatedResourceModel, 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 == "fvRemoteId" {
							FvRemoteIdFvSiteAssociated := getEmptyFvRemoteIdFvSiteAssociatedResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "annotation" {
									FvRemoteIdFvSiteAssociated.Annotation = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "descr" {
									FvRemoteIdFvSiteAssociated.Descr = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "name" {
									FvRemoteIdFvSiteAssociated.Name = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "nameAlias" {
									FvRemoteIdFvSiteAssociated.NameAlias = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "ownerKey" {
									FvRemoteIdFvSiteAssociated.OwnerKey = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "ownerTag" {
									FvRemoteIdFvSiteAssociated.OwnerTag = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "remoteCtxPcTag" {
									FvRemoteIdFvSiteAssociated.RemoteCtxPcTag = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "remotePcTag" {
									FvRemoteIdFvSiteAssociated.RemotePcTag = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "siteId" {
									FvRemoteIdFvSiteAssociated.SiteId = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagAnnotationFvRemoteIdFvSiteAssociatedList := make([]TagAnnotationFvRemoteIdFvSiteAssociatedResourceModel, 0)
							TagTagFvRemoteIdFvSiteAssociatedList := make([]TagTagFvRemoteIdFvSiteAssociatedResourceModel, 0)
							childrenOfFvRemoteIdFvSiteAssociated, childrenOfFvRemoteIdFvSiteAssociatedExist := childClassDetails.(map[string]interface{})["children"]
							if childrenOfFvRemoteIdFvSiteAssociatedExist {
								for _, childFvRemoteIdFvSiteAssociated := range childrenOfFvRemoteIdFvSiteAssociated.([]interface{}) {
									for childClassNameFvRemoteIdFvSiteAssociated, childClassDetailsFvRemoteIdFvSiteAssociated := range childFvRemoteIdFvSiteAssociated.(map[string]interface{}) {
										if childClassNameFvRemoteIdFvSiteAssociated == "tagAnnotation" {
											TagAnnotationFvRemoteIdFvSiteAssociated := getEmptyTagAnnotationFvRemoteIdFvSiteAssociatedResourceModel()
											tagAnnotationchildAttributeValue := childClassDetailsFvRemoteIdFvSiteAssociated.(map[string]interface{})["attributes"].(map[string]interface{})
											for childAttributeName, childAttributeValue := range tagAnnotationchildAttributeValue {
												if childAttributeName == "key" {
													TagAnnotationFvRemoteIdFvSiteAssociated.Key = basetypes.NewStringValue(childAttributeValue.(string))
												}
												if childAttributeName == "value" {
													TagAnnotationFvRemoteIdFvSiteAssociated.Value = basetypes.NewStringValue(childAttributeValue.(string))
												}
											}
											TagAnnotationFvRemoteIdFvSiteAssociatedList = append(TagAnnotationFvRemoteIdFvSiteAssociatedList, TagAnnotationFvRemoteIdFvSiteAssociated)
										}
										if childClassNameFvRemoteIdFvSiteAssociated == "tagTag" {
											TagTagFvRemoteIdFvSiteAssociated := getEmptyTagTagFvRemoteIdFvSiteAssociatedResourceModel()
											tagTagchildAttributeValue := childClassDetailsFvRemoteIdFvSiteAssociated.(map[string]interface{})["attributes"].(map[string]interface{})
											for childAttributeName, childAttributeValue := range tagTagchildAttributeValue {
												if childAttributeName == "key" {
													TagTagFvRemoteIdFvSiteAssociated.Key = basetypes.NewStringValue(childAttributeValue.(string))
												}
												if childAttributeName == "value" {
													TagTagFvRemoteIdFvSiteAssociated.Value = basetypes.NewStringValue(childAttributeValue.(string))
												}
											}
											TagTagFvRemoteIdFvSiteAssociatedList = append(TagTagFvRemoteIdFvSiteAssociatedList, TagTagFvRemoteIdFvSiteAssociated)
										}
									}
								}
							}
							TagAnnotationFvRemoteIdFvSiteAssociatedSet, _ := types.SetValueFrom(ctx, TagAnnotationFvRemoteIdFvSiteAssociatedType, TagAnnotationFvRemoteIdFvSiteAssociatedList)
							FvRemoteIdFvSiteAssociated.TagAnnotation = TagAnnotationFvRemoteIdFvSiteAssociatedSet
							TagTagFvRemoteIdFvSiteAssociatedSet, _ := types.SetValueFrom(ctx, TagTagFvRemoteIdFvSiteAssociatedType, TagTagFvRemoteIdFvSiteAssociatedList)
							FvRemoteIdFvSiteAssociated.TagTag = TagTagFvRemoteIdFvSiteAssociatedSet
							FvRemoteIdFvSiteAssociatedList = append(FvRemoteIdFvSiteAssociatedList, FvRemoteIdFvSiteAssociated)
						}
						if childClassName == "tagAnnotation" {
							TagAnnotationFvSiteAssociated := getEmptyTagAnnotationFvSiteAssociatedResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "key" {
									TagAnnotationFvSiteAssociated.Key = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "value" {
									TagAnnotationFvSiteAssociated.Value = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagAnnotationFvSiteAssociatedList = append(TagAnnotationFvSiteAssociatedList, TagAnnotationFvSiteAssociated)
						}
						if childClassName == "tagTag" {
							TagTagFvSiteAssociated := getEmptyTagTagFvSiteAssociatedResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "key" {
									TagTagFvSiteAssociated.Key = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "value" {
									TagTagFvSiteAssociated.Value = basetypes.NewStringValue(childAttributeValue.(string))
								}

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

func getFvSiteAssociatedRn(ctx context.Context, data *FvSiteAssociatedResourceModel) string {
	return fmt.Sprintf("stAsc")
}

func setFvSiteAssociatedParentDn(ctx context.Context, dn string, data *FvSiteAssociatedResourceModel) {
	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 setFvSiteAssociatedId(ctx context.Context, data *FvSiteAssociatedResourceModel) {
	rn := getFvSiteAssociatedRn(ctx, data)
	data.Id = types.StringValue(fmt.Sprintf("%s/%s", data.ParentDn.ValueString(), rn))
}

func getFvSiteAssociatedFvRemoteIdChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *FvSiteAssociatedResourceModel, fvRemoteIdFvSiteAssociatedPlan, fvRemoteIdFvSiteAssociatedState []FvRemoteIdFvSiteAssociatedResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.FvRemoteId.IsNull() && !data.FvRemoteId.IsUnknown() {
		fvRemoteIdIdentifiers := []FvRemoteIdIdentifier{}
		for _, fvRemoteIdFvSiteAssociated := range fvRemoteIdFvSiteAssociatedPlan {
			FvRemoteIdFvSiteAssociatedChildren := make([]map[string]interface{}, 0)
			childMap := NewAciObject()
			if !fvRemoteIdFvSiteAssociated.Annotation.IsNull() && !fvRemoteIdFvSiteAssociated.Annotation.IsUnknown() {
				childMap.Attributes["annotation"] = fvRemoteIdFvSiteAssociated.Annotation.ValueString()
			} else {
				childMap.Attributes["annotation"] = globalAnnotation
			}
			if !fvRemoteIdFvSiteAssociated.Descr.IsNull() && !fvRemoteIdFvSiteAssociated.Descr.IsUnknown() {
				childMap.Attributes["descr"] = fvRemoteIdFvSiteAssociated.Descr.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.Name.IsNull() && !fvRemoteIdFvSiteAssociated.Name.IsUnknown() {
				childMap.Attributes["name"] = fvRemoteIdFvSiteAssociated.Name.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.NameAlias.IsNull() && !fvRemoteIdFvSiteAssociated.NameAlias.IsUnknown() {
				childMap.Attributes["nameAlias"] = fvRemoteIdFvSiteAssociated.NameAlias.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.OwnerKey.IsNull() && !fvRemoteIdFvSiteAssociated.OwnerKey.IsUnknown() {
				childMap.Attributes["ownerKey"] = fvRemoteIdFvSiteAssociated.OwnerKey.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.OwnerTag.IsNull() && !fvRemoteIdFvSiteAssociated.OwnerTag.IsUnknown() {
				childMap.Attributes["ownerTag"] = fvRemoteIdFvSiteAssociated.OwnerTag.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.RemoteCtxPcTag.IsNull() && !fvRemoteIdFvSiteAssociated.RemoteCtxPcTag.IsUnknown() {
				childMap.Attributes["remoteCtxPcTag"] = fvRemoteIdFvSiteAssociated.RemoteCtxPcTag.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.RemotePcTag.IsNull() && !fvRemoteIdFvSiteAssociated.RemotePcTag.IsUnknown() {
				childMap.Attributes["remotePcTag"] = fvRemoteIdFvSiteAssociated.RemotePcTag.ValueString()
			}
			if !fvRemoteIdFvSiteAssociated.SiteId.IsNull() && !fvRemoteIdFvSiteAssociated.SiteId.IsUnknown() {
				childMap.Attributes["siteId"] = fvRemoteIdFvSiteAssociated.SiteId.ValueString()
			}

			var tagAnnotationFvRemoteIdFvSiteAssociatedPlan, tagAnnotationFvRemoteIdFvSiteAssociatedState []TagAnnotationFvRemoteIdFvSiteAssociatedResourceModel
			fvRemoteIdFvSiteAssociated.TagAnnotation.ElementsAs(ctx, &tagAnnotationFvRemoteIdFvSiteAssociatedPlan, false)
			for _, tagAnnotationFvRemoteIdFvSiteAssociatedstate := range fvRemoteIdFvSiteAssociatedState {
				tagAnnotationFvRemoteIdFvSiteAssociatedstate.TagAnnotation.ElementsAs(ctx, &tagAnnotationFvRemoteIdFvSiteAssociatedState, false)
			}
			if !fvRemoteIdFvSiteAssociated.TagAnnotation.IsNull() && !fvRemoteIdFvSiteAssociated.TagAnnotation.IsUnknown() {
				tagAnnotationIdentifiers := []TagAnnotationIdentifier{}
				for _, tagAnnotationFvRemoteIdFvSiteAssociated := range tagAnnotationFvRemoteIdFvSiteAssociatedPlan {
					tagAnnotationFvRemoteIdFvSiteAssociatedChildMap := NewAciObject()
					if !tagAnnotationFvRemoteIdFvSiteAssociated.Key.IsNull() && !tagAnnotationFvRemoteIdFvSiteAssociated.Key.IsUnknown() {
						tagAnnotationFvRemoteIdFvSiteAssociatedChildMap.Attributes["key"] = tagAnnotationFvRemoteIdFvSiteAssociated.Key.ValueString()
					}
					if !tagAnnotationFvRemoteIdFvSiteAssociated.Value.IsNull() && !tagAnnotationFvRemoteIdFvSiteAssociated.Value.IsUnknown() {
						tagAnnotationFvRemoteIdFvSiteAssociatedChildMap.Attributes["value"] = tagAnnotationFvRemoteIdFvSiteAssociated.Value.ValueString()
					}
					FvRemoteIdFvSiteAssociatedChildren = append(FvRemoteIdFvSiteAssociatedChildren, map[string]interface{}{"tagAnnotation": tagAnnotationFvRemoteIdFvSiteAssociatedChildMap})
					tagAnnotationIdentifier := TagAnnotationIdentifier{}
					tagAnnotationIdentifier.Key = tagAnnotationFvRemoteIdFvSiteAssociated.Key
					tagAnnotationIdentifiers = append(tagAnnotationIdentifiers, tagAnnotationIdentifier)
				}
				for _, tagAnnotationFvRemoteIdFvSiteAssociated := range tagAnnotationFvRemoteIdFvSiteAssociatedState {
					delete := true
					for _, tagAnnotationIdentifier := range tagAnnotationIdentifiers {
						if tagAnnotationIdentifier.Key == tagAnnotationFvRemoteIdFvSiteAssociated.Key {
							delete = false
							break
						}
					}
					if delete {
						tagAnnotationFvRemoteIdFvSiteAssociatedChildMapForDelete := NewAciObject()
						tagAnnotationFvRemoteIdFvSiteAssociatedChildMapForDelete.Attributes["status"] = "deleted"
						tagAnnotationFvRemoteIdFvSiteAssociatedChildMapForDelete.Attributes["key"] = tagAnnotationFvRemoteIdFvSiteAssociated.Key.ValueString()
						FvRemoteIdFvSiteAssociatedChildren = append(FvRemoteIdFvSiteAssociatedChildren, map[string]interface{}{"tagAnnotation": tagAnnotationFvRemoteIdFvSiteAssociatedChildMapForDelete})
					}
				}
			}

			var tagTagFvRemoteIdFvSiteAssociatedPlan, tagTagFvRemoteIdFvSiteAssociatedState []TagTagFvRemoteIdFvSiteAssociatedResourceModel
			fvRemoteIdFvSiteAssociated.TagTag.ElementsAs(ctx, &tagTagFvRemoteIdFvSiteAssociatedPlan, false)
			for _, tagTagFvRemoteIdFvSiteAssociatedstate := range fvRemoteIdFvSiteAssociatedState {
				tagTagFvRemoteIdFvSiteAssociatedstate.TagTag.ElementsAs(ctx, &tagTagFvRemoteIdFvSiteAssociatedState, false)
			}
			if !fvRemoteIdFvSiteAssociated.TagTag.IsNull() && !fvRemoteIdFvSiteAssociated.TagTag.IsUnknown() {
				tagTagIdentifiers := []TagTagIdentifier{}
				for _, tagTagFvRemoteIdFvSiteAssociated := range tagTagFvRemoteIdFvSiteAssociatedPlan {
					tagTagFvRemoteIdFvSiteAssociatedChildMap := NewAciObject()
					if !tagTagFvRemoteIdFvSiteAssociated.Key.IsNull() && !tagTagFvRemoteIdFvSiteAssociated.Key.IsUnknown() {
						tagTagFvRemoteIdFvSiteAssociatedChildMap.Attributes["key"] = tagTagFvRemoteIdFvSiteAssociated.Key.ValueString()
					}
					if !tagTagFvRemoteIdFvSiteAssociated.Value.IsNull() && !tagTagFvRemoteIdFvSiteAssociated.Value.IsUnknown() {
						tagTagFvRemoteIdFvSiteAssociatedChildMap.Attributes["value"] = tagTagFvRemoteIdFvSiteAssociated.Value.ValueString()
					}
					FvRemoteIdFvSiteAssociatedChildren = append(FvRemoteIdFvSiteAssociatedChildren, map[string]interface{}{"tagTag": tagTagFvRemoteIdFvSiteAssociatedChildMap})
					tagTagIdentifier := TagTagIdentifier{}
					tagTagIdentifier.Key = tagTagFvRemoteIdFvSiteAssociated.Key
					tagTagIdentifiers = append(tagTagIdentifiers, tagTagIdentifier)
				}
				for _, tagTagFvRemoteIdFvSiteAssociated := range tagTagFvRemoteIdFvSiteAssociatedState {
					delete := true
					for _, tagTagIdentifier := range tagTagIdentifiers {
						if tagTagIdentifier.Key == tagTagFvRemoteIdFvSiteAssociated.Key {
							delete = false
							break
						}
					}
					if delete {
						tagTagFvRemoteIdFvSiteAssociatedChildMapForDelete := NewAciObject()
						tagTagFvRemoteIdFvSiteAssociatedChildMapForDelete.Attributes["status"] = "deleted"
						tagTagFvRemoteIdFvSiteAssociatedChildMapForDelete.Attributes["key"] = tagTagFvRemoteIdFvSiteAssociated.Key.ValueString()
						FvRemoteIdFvSiteAssociatedChildren = append(FvRemoteIdFvSiteAssociatedChildren, map[string]interface{}{"tagTag": tagTagFvRemoteIdFvSiteAssociatedChildMapForDelete})
					}
				}
			}
			childMap.Children = FvRemoteIdFvSiteAssociatedChildren
			childPayloads = append(childPayloads, map[string]interface{}{"fvRemoteId": childMap})
			fvRemoteIdIdentifier := FvRemoteIdIdentifier{}
			fvRemoteIdIdentifier.SiteId = fvRemoteIdFvSiteAssociated.SiteId
			fvRemoteIdIdentifiers = append(fvRemoteIdIdentifiers, fvRemoteIdIdentifier)
		}
		for _, fvRemoteId := range fvRemoteIdFvSiteAssociatedState {
			delete := true
			for _, fvRemoteIdIdentifier := range fvRemoteIdIdentifiers {
				if fvRemoteIdIdentifier.SiteId == fvRemoteId.SiteId {
					delete = false
					break
				}
			}
			if delete {
				fvRemoteIdChildMapForDelete := NewAciObject()
				fvRemoteIdChildMapForDelete.Attributes["status"] = "deleted"
				fvRemoteIdChildMapForDelete.Attributes["siteId"] = fvRemoteId.SiteId.ValueString()
				childPayloads = append(childPayloads, map[string]interface{}{"fvRemoteId": fvRemoteIdChildMapForDelete})
			}
		}
	} else {
		data.FvRemoteId = types.SetNull(data.FvRemoteId.ElementType(ctx))
	}

	return childPayloads
}

func getFvSiteAssociatedTagAnnotationChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *FvSiteAssociatedResourceModel, tagAnnotationFvSiteAssociatedPlan, tagAnnotationFvSiteAssociatedState []TagAnnotationFvSiteAssociatedResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.TagAnnotation.IsNull() && !data.TagAnnotation.IsUnknown() {
		tagAnnotationIdentifiers := []TagAnnotationIdentifier{}
		for _, tagAnnotationFvSiteAssociated := range tagAnnotationFvSiteAssociatedPlan {
			childMap := NewAciObject()
			if !tagAnnotationFvSiteAssociated.Key.IsNull() && !tagAnnotationFvSiteAssociated.Key.IsUnknown() {
				childMap.Attributes["key"] = tagAnnotationFvSiteAssociated.Key.ValueString()
			}
			if !tagAnnotationFvSiteAssociated.Value.IsNull() && !tagAnnotationFvSiteAssociated.Value.IsUnknown() {
				childMap.Attributes["value"] = tagAnnotationFvSiteAssociated.Value.ValueString()
			}
			childPayloads = append(childPayloads, map[string]interface{}{"tagAnnotation": childMap})
			tagAnnotationIdentifier := TagAnnotationIdentifier{}
			tagAnnotationIdentifier.Key = tagAnnotationFvSiteAssociated.Key
			tagAnnotationIdentifiers = append(tagAnnotationIdentifiers, tagAnnotationIdentifier)
		}
		for _, tagAnnotation := range tagAnnotationFvSiteAssociatedState {
			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 getFvSiteAssociatedTagTagChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *FvSiteAssociatedResourceModel, tagTagFvSiteAssociatedPlan, tagTagFvSiteAssociatedState []TagTagFvSiteAssociatedResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.TagTag.IsNull() && !data.TagTag.IsUnknown() {
		tagTagIdentifiers := []TagTagIdentifier{}
		for _, tagTagFvSiteAssociated := range tagTagFvSiteAssociatedPlan {
			childMap := NewAciObject()
			if !tagTagFvSiteAssociated.Key.IsNull() && !tagTagFvSiteAssociated.Key.IsUnknown() {
				childMap.Attributes["key"] = tagTagFvSiteAssociated.Key.ValueString()
			}
			if !tagTagFvSiteAssociated.Value.IsNull() && !tagTagFvSiteAssociated.Value.IsUnknown() {
				childMap.Attributes["value"] = tagTagFvSiteAssociated.Value.ValueString()
			}
			childPayloads = append(childPayloads, map[string]interface{}{"tagTag": childMap})
			tagTagIdentifier := TagTagIdentifier{}
			tagTagIdentifier.Key = tagTagFvSiteAssociated.Key
			tagTagIdentifiers = append(tagTagIdentifiers, tagTagIdentifier)
		}
		for _, tagTag := range tagTagFvSiteAssociatedState {
			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 getFvSiteAssociatedCreateJsonPayload(ctx context.Context, diags *diag.Diagnostics, createType bool, data *FvSiteAssociatedResourceModel, fvRemoteIdPlan, fvRemoteIdState []FvRemoteIdFvSiteAssociatedResourceModel, tagAnnotationPlan, tagAnnotationState []TagAnnotationFvSiteAssociatedResourceModel, tagTagPlan, tagTagState []TagTagFvSiteAssociatedResourceModel) *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{}{}

	FvRemoteIdchildPayloads := getFvSiteAssociatedFvRemoteIdChildPayloads(ctx, diags, data, fvRemoteIdPlan, fvRemoteIdState)
	if FvRemoteIdchildPayloads == nil {
		return nil
	}
	childPayloads = append(childPayloads, FvRemoteIdchildPayloads...)

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

	TagTagchildPayloads := getFvSiteAssociatedTagTagChildPayloads(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.Descr.IsNull() && !data.Descr.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["descr"] = data.Descr.ValueString()
	}
	if !data.Name.IsNull() && !data.Name.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["name"] = data.Name.ValueString()
	}
	if !data.NameAlias.IsNull() && !data.NameAlias.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["nameAlias"] = data.NameAlias.ValueString()
	}
	if !data.OwnerKey.IsNull() && !data.OwnerKey.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["ownerKey"] = data.OwnerKey.ValueString()
	}
	if !data.OwnerTag.IsNull() && !data.OwnerTag.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["ownerTag"] = data.OwnerTag.ValueString()
	}
	if !data.SiteId.IsNull() && !data.SiteId.IsUnknown() {
		payloadMap["attributes"].(map[string]string)["siteId"] = data.SiteId.ValueString()
	}
	payload, err := json.Marshal(map[string]interface{}{"fvSiteAssociated": 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
}
