// 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 = &VzTSubjResource{}
var _ resource.ResourceWithImportState = &VzTSubjResource{}

func NewVzTSubjResource() resource.Resource {
	return &VzTSubjResource{}
}

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

// VzTSubjResourceModel describes the resource data model.
type VzTSubjResourceModel 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"`
	TagAnnotation types.Set    `tfsdk:"annotations"`
	TagTag        types.Set    `tfsdk:"tags"`
	VzRsDenyRule  types.Set    `tfsdk:"relation_to_filters"`
}

func getEmptyVzTSubjResourceModel() *VzTSubjResourceModel {
	return &VzTSubjResourceModel{
		Id:         basetypes.NewStringNull(),
		ParentDn:   basetypes.NewStringNull(),
		Annotation: basetypes.NewStringNull(),
		Descr:      basetypes.NewStringNull(),
		Name:       basetypes.NewStringNull(),
		NameAlias:  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,
			},
		}),
		VzRsDenyRule: types.SetNull(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"annotation":  types.StringType,
				"directives":  types.SetType{ElemType: types.StringType},
				"filter_name": types.StringType,
				"annotations": types.SetType{ElemType: TagAnnotationVzRsDenyRuleVzTSubjType},
				"tags":        types.SetType{ElemType: TagTagVzRsDenyRuleVzTSubjType},
			},
		}),
	}
}

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

func getEmptyTagAnnotationVzTSubjResourceModel() TagAnnotationVzTSubjResourceModel {
	return TagAnnotationVzTSubjResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

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

func getEmptyTagTagVzTSubjResourceModel() TagTagVzTSubjResourceModel {
	return TagTagVzTSubjResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

// VzRsDenyRuleVzTSubjResourceModel describes the resource data model for the children without relation ships.
type VzRsDenyRuleVzTSubjResourceModel struct {
	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 getEmptyVzRsDenyRuleVzTSubjResourceModel() VzRsDenyRuleVzTSubjResourceModel {
	return VzRsDenyRuleVzTSubjResourceModel{
		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,
			},
		}),
	}
}

var VzRsDenyRuleVzTSubjType = types.ObjectType{
	AttrTypes: map[string]attr.Type{
		"annotation":  types.StringType,
		"directives":  types.SetType{ElemType: types.StringType},
		"filter_name": types.StringType,
		"annotations": types.SetType{ElemType: TagAnnotationVzRsDenyRuleVzTSubjType},
		"tags":        types.SetType{ElemType: TagTagVzRsDenyRuleVzTSubjType},
	},
}

func VzRsDenyRuleVzTSubjSetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate(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 []VzRsDenyRuleVzTSubjResourceModel
	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.Directives.IsNull() {
				nullInStateFound = true
				planSetValues[index].Directives = basetypes.NewSetNull(types.StringType)
			}
			if stateValue.TnVzFilterName.IsNull() {
				nullInStateFound = true
				planSetValues[index].TnVzFilterName = 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, VzRsDenyRuleVzTSubjType, planSetValues)
	return planSet

}

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

func getEmptyTagAnnotationVzRsDenyRuleVzTSubjResourceModel() TagAnnotationVzRsDenyRuleVzTSubjResourceModel {
	return TagAnnotationVzRsDenyRuleVzTSubjResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

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

func getEmptyTagTagVzRsDenyRuleVzTSubjResourceModel() TagTagVzRsDenyRuleVzTSubjResourceModel {
	return TagTagVzRsDenyRuleVzTSubjResourceModel{
		Key:   basetypes.NewStringNull(),
		Value: basetypes.NewStringNull(),
	}
}

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

type VzTSubjIdentifier struct {
	Name types.String
}

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

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

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

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

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

		Attributes: map[string]schema.Attribute{
			"id": schema.StringAttribute{
				Computed:            true,
				MarkdownDescription: "The distinguished name (DN) of the Taboo Contract Subject 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 Taboo Contract Subject object.`,
			},
			"description": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The description of the Taboo Contract Subject object.`,
			},
			"name": schema.StringAttribute{
				Required: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
					stringplanmodifier.RequiresReplace(),
				},
				MarkdownDescription: `The name of the Taboo Contract Subject object.`,
			},
			"name_alias": schema.StringAttribute{
				Optional: true,
				Computed: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
					SetToStringNullWhenStateIsNullPlanIsUnknownDuringUpdate(),
				},
				MarkdownDescription: `The name alias of the Taboo Contract Subject 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.`,
						},
					},
				},
			},
			"relation_to_filters": schema.SetNestedAttribute{
				MarkdownDescription: `A filter is a group of resolvable filter entries. Each filter entry is a combination of network traffic classification properties. Note that this relation is an internal object.`,
				Optional:            true,
				Computed:            true,
				PlanModifiers: []planmodifier.Set{
					setplanmodifier.UseStateForUnknown(),
					SetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate(VzRsDenyRuleVzTSubjSetToSetNullWhenStateIsNullPlanIsUnknownDuringUpdate),
				},
				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 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(),
							},
							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(),
							},
							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_taboo_contract_subject")
}

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

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

	var data *VzTSubjResourceModel

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

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

	var tagAnnotationPlan, tagAnnotationState []TagAnnotationVzTSubjResourceModel
	data.TagAnnotation.ElementsAs(ctx, &tagAnnotationPlan, false)
	stateData.TagAnnotation.ElementsAs(ctx, &tagAnnotationState, false)
	var tagTagPlan, tagTagState []TagTagVzTSubjResourceModel
	data.TagTag.ElementsAs(ctx, &tagTagPlan, false)
	stateData.TagTag.ElementsAs(ctx, &tagTagState, false)
	var vzRsDenyRulePlan, vzRsDenyRuleState []VzRsDenyRuleVzTSubjResourceModel
	data.VzRsDenyRule.ElementsAs(ctx, &vzRsDenyRulePlan, false)
	stateData.VzRsDenyRule.ElementsAs(ctx, &vzRsDenyRuleState, false)
	jsonPayload := getVzTSubjCreateJsonPayload(ctx, &resp.Diagnostics, true, data, tagAnnotationPlan, tagAnnotationState, tagTagPlan, tagTagState, vzRsDenyRulePlan, vzRsDenyRuleState)

	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
	}

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

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

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

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

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

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

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

	var tagAnnotationPlan, tagAnnotationState []TagAnnotationVzTSubjResourceModel
	data.TagAnnotation.ElementsAs(ctx, &tagAnnotationPlan, false)
	stateData.TagAnnotation.ElementsAs(ctx, &tagAnnotationState, false)
	var tagTagPlan, tagTagState []TagTagVzTSubjResourceModel
	data.TagTag.ElementsAs(ctx, &tagTagPlan, false)
	stateData.TagTag.ElementsAs(ctx, &tagTagState, false)
	var vzRsDenyRulePlan, vzRsDenyRuleState []VzRsDenyRuleVzTSubjResourceModel
	data.VzRsDenyRule.ElementsAs(ctx, &vzRsDenyRulePlan, false)
	stateData.VzRsDenyRule.ElementsAs(ctx, &vzRsDenyRuleState, false)
	jsonPayload := getVzTSubjCreateJsonPayload(ctx, &resp.Diagnostics, false, data, tagAnnotationPlan, tagAnnotationState, tagTagPlan, tagTagState, vzRsDenyRulePlan, vzRsDenyRuleState)

	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
	}

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

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

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

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

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

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

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

	readData := getEmptyVzTSubjResourceModel()

	if diags.HasError() {
		return
	}
	if requestData.Search("imdata").Search("vzTSubj").Data() != nil {
		classReadInfo := requestData.Search("imdata").Search("vzTSubj").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))
					setVzTSubjParentDn(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))
				}
			}
			TagAnnotationVzTSubjList := make([]TagAnnotationVzTSubjResourceModel, 0)
			TagTagVzTSubjList := make([]TagTagVzTSubjResourceModel, 0)
			VzRsDenyRuleVzTSubjList := make([]VzRsDenyRuleVzTSubjResourceModel, 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" {
							TagAnnotationVzTSubj := getEmptyTagAnnotationVzTSubjResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "key" {
									TagAnnotationVzTSubj.Key = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "value" {
									TagAnnotationVzTSubj.Value = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagAnnotationVzTSubjList = append(TagAnnotationVzTSubjList, TagAnnotationVzTSubj)
						}
						if childClassName == "tagTag" {
							TagTagVzTSubj := getEmptyTagTagVzTSubjResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "key" {
									TagTagVzTSubj.Key = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "value" {
									TagTagVzTSubj.Value = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagTagVzTSubjList = append(TagTagVzTSubjList, TagTagVzTSubj)
						}
						if childClassName == "vzRsDenyRule" {
							VzRsDenyRuleVzTSubj := getEmptyVzRsDenyRuleVzTSubjResourceModel()
							for childAttributeName, childAttributeValue := range childAttributes {
								if childAttributeName == "annotation" {
									VzRsDenyRuleVzTSubj.Annotation = basetypes.NewStringValue(childAttributeValue.(string))
								}
								if childAttributeName == "directives" {
									directivesList := make([]string, 0)
									if childAttributeValue.(string) != "" {
										directivesList = strings.Split(childAttributeValue.(string), ",")
									}
									directivesSet, _ := types.SetValueFrom(ctx, basetypes.StringType{}, directivesList)
									VzRsDenyRuleVzTSubj.Directives = directivesSet

								}
								if childAttributeName == "tnVzFilterName" {
									VzRsDenyRuleVzTSubj.TnVzFilterName = basetypes.NewStringValue(childAttributeValue.(string))
								}

							}
							TagAnnotationVzRsDenyRuleVzTSubjList := make([]TagAnnotationVzRsDenyRuleVzTSubjResourceModel, 0)
							TagTagVzRsDenyRuleVzTSubjList := make([]TagTagVzRsDenyRuleVzTSubjResourceModel, 0)
							childrenOfVzRsDenyRuleVzTSubj, childrenOfVzRsDenyRuleVzTSubjExist := childClassDetails.(map[string]interface{})["children"]
							if childrenOfVzRsDenyRuleVzTSubjExist {
								for _, childVzRsDenyRuleVzTSubj := range childrenOfVzRsDenyRuleVzTSubj.([]interface{}) {
									for childClassNameVzRsDenyRuleVzTSubj, childClassDetailsVzRsDenyRuleVzTSubj := range childVzRsDenyRuleVzTSubj.(map[string]interface{}) {
										if childClassNameVzRsDenyRuleVzTSubj == "tagAnnotation" {
											TagAnnotationVzRsDenyRuleVzTSubj := getEmptyTagAnnotationVzRsDenyRuleVzTSubjResourceModel()
											tagAnnotationchildAttributeValue := childClassDetailsVzRsDenyRuleVzTSubj.(map[string]interface{})["attributes"].(map[string]interface{})
											for childAttributeName, childAttributeValue := range tagAnnotationchildAttributeValue {
												if childAttributeName == "key" {
													TagAnnotationVzRsDenyRuleVzTSubj.Key = basetypes.NewStringValue(childAttributeValue.(string))
												}
												if childAttributeName == "value" {
													TagAnnotationVzRsDenyRuleVzTSubj.Value = basetypes.NewStringValue(childAttributeValue.(string))
												}
											}
											TagAnnotationVzRsDenyRuleVzTSubjList = append(TagAnnotationVzRsDenyRuleVzTSubjList, TagAnnotationVzRsDenyRuleVzTSubj)
										}
										if childClassNameVzRsDenyRuleVzTSubj == "tagTag" {
											TagTagVzRsDenyRuleVzTSubj := getEmptyTagTagVzRsDenyRuleVzTSubjResourceModel()
											tagTagchildAttributeValue := childClassDetailsVzRsDenyRuleVzTSubj.(map[string]interface{})["attributes"].(map[string]interface{})
											for childAttributeName, childAttributeValue := range tagTagchildAttributeValue {
												if childAttributeName == "key" {
													TagTagVzRsDenyRuleVzTSubj.Key = basetypes.NewStringValue(childAttributeValue.(string))
												}
												if childAttributeName == "value" {
													TagTagVzRsDenyRuleVzTSubj.Value = basetypes.NewStringValue(childAttributeValue.(string))
												}
											}
											TagTagVzRsDenyRuleVzTSubjList = append(TagTagVzRsDenyRuleVzTSubjList, TagTagVzRsDenyRuleVzTSubj)
										}
									}
								}
							}
							TagAnnotationVzRsDenyRuleVzTSubjSet, _ := types.SetValueFrom(ctx, TagAnnotationVzRsDenyRuleVzTSubjType, TagAnnotationVzRsDenyRuleVzTSubjList)
							VzRsDenyRuleVzTSubj.TagAnnotation = TagAnnotationVzRsDenyRuleVzTSubjSet
							TagTagVzRsDenyRuleVzTSubjSet, _ := types.SetValueFrom(ctx, TagTagVzRsDenyRuleVzTSubjType, TagTagVzRsDenyRuleVzTSubjList)
							VzRsDenyRuleVzTSubj.TagTag = TagTagVzRsDenyRuleVzTSubjSet
							VzRsDenyRuleVzTSubjList = append(VzRsDenyRuleVzTSubjList, VzRsDenyRuleVzTSubj)
						}
					}
				}
			}
			tagAnnotationSet, _ := types.SetValueFrom(ctx, readData.TagAnnotation.ElementType(ctx), TagAnnotationVzTSubjList)
			readData.TagAnnotation = tagAnnotationSet
			tagTagSet, _ := types.SetValueFrom(ctx, readData.TagTag.ElementType(ctx), TagTagVzTSubjList)
			readData.TagTag = tagTagSet
			vzRsDenyRuleSet, _ := types.SetValueFrom(ctx, readData.VzRsDenyRule.ElementType(ctx), VzRsDenyRuleVzTSubjList)
			readData.VzRsDenyRule = vzRsDenyRuleSet
		} else {
			diags.AddError(
				"too many results in response",
				fmt.Sprintf("%v matches returned for class 'vzTSubj'. Please report this issue to the provider developers.", len(classReadInfo)),
			)
		}
	} else {
		readData.Id = basetypes.NewStringNull()
	}
	*data = *readData
}

func getVzTSubjRn(ctx context.Context, data *VzTSubjResourceModel) string {
	return fmt.Sprintf("tsubj-%s", data.Name.ValueString())
}

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

func getVzTSubjTagAnnotationChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *VzTSubjResourceModel, tagAnnotationVzTSubjPlan, tagAnnotationVzTSubjState []TagAnnotationVzTSubjResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.TagAnnotation.IsNull() && !data.TagAnnotation.IsUnknown() {
		tagAnnotationIdentifiers := []TagAnnotationIdentifier{}
		for _, tagAnnotationVzTSubj := range tagAnnotationVzTSubjPlan {
			childMap := NewAciObject()
			if !tagAnnotationVzTSubj.Key.IsNull() && !tagAnnotationVzTSubj.Key.IsUnknown() {
				childMap.Attributes["key"] = tagAnnotationVzTSubj.Key.ValueString()
			}
			if !tagAnnotationVzTSubj.Value.IsNull() && !tagAnnotationVzTSubj.Value.IsUnknown() {
				childMap.Attributes["value"] = tagAnnotationVzTSubj.Value.ValueString()
			}
			childPayloads = append(childPayloads, map[string]interface{}{"tagAnnotation": childMap})
			tagAnnotationIdentifier := TagAnnotationIdentifier{}
			tagAnnotationIdentifier.Key = tagAnnotationVzTSubj.Key
			tagAnnotationIdentifiers = append(tagAnnotationIdentifiers, tagAnnotationIdentifier)
		}
		for _, tagAnnotation := range tagAnnotationVzTSubjState {
			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 getVzTSubjTagTagChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *VzTSubjResourceModel, tagTagVzTSubjPlan, tagTagVzTSubjState []TagTagVzTSubjResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.TagTag.IsNull() && !data.TagTag.IsUnknown() {
		tagTagIdentifiers := []TagTagIdentifier{}
		for _, tagTagVzTSubj := range tagTagVzTSubjPlan {
			childMap := NewAciObject()
			if !tagTagVzTSubj.Key.IsNull() && !tagTagVzTSubj.Key.IsUnknown() {
				childMap.Attributes["key"] = tagTagVzTSubj.Key.ValueString()
			}
			if !tagTagVzTSubj.Value.IsNull() && !tagTagVzTSubj.Value.IsUnknown() {
				childMap.Attributes["value"] = tagTagVzTSubj.Value.ValueString()
			}
			childPayloads = append(childPayloads, map[string]interface{}{"tagTag": childMap})
			tagTagIdentifier := TagTagIdentifier{}
			tagTagIdentifier.Key = tagTagVzTSubj.Key
			tagTagIdentifiers = append(tagTagIdentifiers, tagTagIdentifier)
		}
		for _, tagTag := range tagTagVzTSubjState {
			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 getVzTSubjVzRsDenyRuleChildPayloads(ctx context.Context, diags *diag.Diagnostics, data *VzTSubjResourceModel, vzRsDenyRuleVzTSubjPlan, vzRsDenyRuleVzTSubjState []VzRsDenyRuleVzTSubjResourceModel) []map[string]interface{} {
	childPayloads := []map[string]interface{}{}
	if !data.VzRsDenyRule.IsNull() && !data.VzRsDenyRule.IsUnknown() {
		vzRsDenyRuleIdentifiers := []VzRsDenyRuleIdentifier{}
		for _, vzRsDenyRuleVzTSubj := range vzRsDenyRuleVzTSubjPlan {
			VzRsDenyRuleVzTSubjChildren := make([]map[string]interface{}, 0)
			childMap := NewAciObject()
			if !vzRsDenyRuleVzTSubj.Annotation.IsNull() && !vzRsDenyRuleVzTSubj.Annotation.IsUnknown() {
				childMap.Attributes["annotation"] = vzRsDenyRuleVzTSubj.Annotation.ValueString()
			} else {
				childMap.Attributes["annotation"] = globalAnnotation
			}
			if !vzRsDenyRuleVzTSubj.Directives.IsNull() && !vzRsDenyRuleVzTSubj.Directives.IsUnknown() {
				var tmpDirectives []string
				vzRsDenyRuleVzTSubj.Directives.ElementsAs(ctx, &tmpDirectives, false)
				childMap.Attributes["directives"] = strings.Join(tmpDirectives, ",")
			}
			if !vzRsDenyRuleVzTSubj.TnVzFilterName.IsNull() && !vzRsDenyRuleVzTSubj.TnVzFilterName.IsUnknown() {
				childMap.Attributes["tnVzFilterName"] = vzRsDenyRuleVzTSubj.TnVzFilterName.ValueString()
			}

			var tagAnnotationVzRsDenyRuleVzTSubjPlan, tagAnnotationVzRsDenyRuleVzTSubjState []TagAnnotationVzRsDenyRuleVzTSubjResourceModel
			vzRsDenyRuleVzTSubj.TagAnnotation.ElementsAs(ctx, &tagAnnotationVzRsDenyRuleVzTSubjPlan, false)
			for _, tagAnnotationVzRsDenyRuleVzTSubjstate := range vzRsDenyRuleVzTSubjState {
				tagAnnotationVzRsDenyRuleVzTSubjstate.TagAnnotation.ElementsAs(ctx, &tagAnnotationVzRsDenyRuleVzTSubjState, false)
			}
			if !vzRsDenyRuleVzTSubj.TagAnnotation.IsNull() && !vzRsDenyRuleVzTSubj.TagAnnotation.IsUnknown() {
				tagAnnotationIdentifiers := []TagAnnotationIdentifier{}
				for _, tagAnnotationVzRsDenyRuleVzTSubj := range tagAnnotationVzRsDenyRuleVzTSubjPlan {
					tagAnnotationVzRsDenyRuleVzTSubjChildMap := NewAciObject()
					if !tagAnnotationVzRsDenyRuleVzTSubj.Key.IsNull() && !tagAnnotationVzRsDenyRuleVzTSubj.Key.IsUnknown() {
						tagAnnotationVzRsDenyRuleVzTSubjChildMap.Attributes["key"] = tagAnnotationVzRsDenyRuleVzTSubj.Key.ValueString()
					}
					if !tagAnnotationVzRsDenyRuleVzTSubj.Value.IsNull() && !tagAnnotationVzRsDenyRuleVzTSubj.Value.IsUnknown() {
						tagAnnotationVzRsDenyRuleVzTSubjChildMap.Attributes["value"] = tagAnnotationVzRsDenyRuleVzTSubj.Value.ValueString()
					}
					VzRsDenyRuleVzTSubjChildren = append(VzRsDenyRuleVzTSubjChildren, map[string]interface{}{"tagAnnotation": tagAnnotationVzRsDenyRuleVzTSubjChildMap})
					tagAnnotationIdentifier := TagAnnotationIdentifier{}
					tagAnnotationIdentifier.Key = tagAnnotationVzRsDenyRuleVzTSubj.Key
					tagAnnotationIdentifiers = append(tagAnnotationIdentifiers, tagAnnotationIdentifier)
				}
				for _, tagAnnotationVzRsDenyRuleVzTSubj := range tagAnnotationVzRsDenyRuleVzTSubjState {
					delete := true
					for _, tagAnnotationIdentifier := range tagAnnotationIdentifiers {
						if tagAnnotationIdentifier.Key == tagAnnotationVzRsDenyRuleVzTSubj.Key {
							delete = false
							break
						}
					}
					if delete {
						tagAnnotationVzRsDenyRuleVzTSubjChildMapForDelete := NewAciObject()
						tagAnnotationVzRsDenyRuleVzTSubjChildMapForDelete.Attributes["status"] = "deleted"
						tagAnnotationVzRsDenyRuleVzTSubjChildMapForDelete.Attributes["key"] = tagAnnotationVzRsDenyRuleVzTSubj.Key.ValueString()
						VzRsDenyRuleVzTSubjChildren = append(VzRsDenyRuleVzTSubjChildren, map[string]interface{}{"tagAnnotation": tagAnnotationVzRsDenyRuleVzTSubjChildMapForDelete})
					}
				}
			}

			var tagTagVzRsDenyRuleVzTSubjPlan, tagTagVzRsDenyRuleVzTSubjState []TagTagVzRsDenyRuleVzTSubjResourceModel
			vzRsDenyRuleVzTSubj.TagTag.ElementsAs(ctx, &tagTagVzRsDenyRuleVzTSubjPlan, false)
			for _, tagTagVzRsDenyRuleVzTSubjstate := range vzRsDenyRuleVzTSubjState {
				tagTagVzRsDenyRuleVzTSubjstate.TagTag.ElementsAs(ctx, &tagTagVzRsDenyRuleVzTSubjState, false)
			}
			if !vzRsDenyRuleVzTSubj.TagTag.IsNull() && !vzRsDenyRuleVzTSubj.TagTag.IsUnknown() {
				tagTagIdentifiers := []TagTagIdentifier{}
				for _, tagTagVzRsDenyRuleVzTSubj := range tagTagVzRsDenyRuleVzTSubjPlan {
					tagTagVzRsDenyRuleVzTSubjChildMap := NewAciObject()
					if !tagTagVzRsDenyRuleVzTSubj.Key.IsNull() && !tagTagVzRsDenyRuleVzTSubj.Key.IsUnknown() {
						tagTagVzRsDenyRuleVzTSubjChildMap.Attributes["key"] = tagTagVzRsDenyRuleVzTSubj.Key.ValueString()
					}
					if !tagTagVzRsDenyRuleVzTSubj.Value.IsNull() && !tagTagVzRsDenyRuleVzTSubj.Value.IsUnknown() {
						tagTagVzRsDenyRuleVzTSubjChildMap.Attributes["value"] = tagTagVzRsDenyRuleVzTSubj.Value.ValueString()
					}
					VzRsDenyRuleVzTSubjChildren = append(VzRsDenyRuleVzTSubjChildren, map[string]interface{}{"tagTag": tagTagVzRsDenyRuleVzTSubjChildMap})
					tagTagIdentifier := TagTagIdentifier{}
					tagTagIdentifier.Key = tagTagVzRsDenyRuleVzTSubj.Key
					tagTagIdentifiers = append(tagTagIdentifiers, tagTagIdentifier)
				}
				for _, tagTagVzRsDenyRuleVzTSubj := range tagTagVzRsDenyRuleVzTSubjState {
					delete := true
					for _, tagTagIdentifier := range tagTagIdentifiers {
						if tagTagIdentifier.Key == tagTagVzRsDenyRuleVzTSubj.Key {
							delete = false
							break
						}
					}
					if delete {
						tagTagVzRsDenyRuleVzTSubjChildMapForDelete := NewAciObject()
						tagTagVzRsDenyRuleVzTSubjChildMapForDelete.Attributes["status"] = "deleted"
						tagTagVzRsDenyRuleVzTSubjChildMapForDelete.Attributes["key"] = tagTagVzRsDenyRuleVzTSubj.Key.ValueString()
						VzRsDenyRuleVzTSubjChildren = append(VzRsDenyRuleVzTSubjChildren, map[string]interface{}{"tagTag": tagTagVzRsDenyRuleVzTSubjChildMapForDelete})
					}
				}
			}
			childMap.Children = VzRsDenyRuleVzTSubjChildren
			childPayloads = append(childPayloads, map[string]interface{}{"vzRsDenyRule": childMap})
			vzRsDenyRuleIdentifier := VzRsDenyRuleIdentifier{}
			vzRsDenyRuleIdentifier.TnVzFilterName = vzRsDenyRuleVzTSubj.TnVzFilterName
			vzRsDenyRuleIdentifiers = append(vzRsDenyRuleIdentifiers, vzRsDenyRuleIdentifier)
		}
		for _, vzRsDenyRule := range vzRsDenyRuleVzTSubjState {
			delete := true
			for _, vzRsDenyRuleIdentifier := range vzRsDenyRuleIdentifiers {
				if vzRsDenyRuleIdentifier.TnVzFilterName == vzRsDenyRule.TnVzFilterName {
					delete = false
					break
				}
			}
			if delete {
				vzRsDenyRuleChildMapForDelete := NewAciObject()
				vzRsDenyRuleChildMapForDelete.Attributes["status"] = "deleted"
				vzRsDenyRuleChildMapForDelete.Attributes["tnVzFilterName"] = vzRsDenyRule.TnVzFilterName.ValueString()
				childPayloads = append(childPayloads, map[string]interface{}{"vzRsDenyRule": vzRsDenyRuleChildMapForDelete})
			}
		}
	} else {
		data.VzRsDenyRule = types.SetNull(data.VzRsDenyRule.ElementType(ctx))
	}

	return childPayloads
}

func getVzTSubjCreateJsonPayload(ctx context.Context, diags *diag.Diagnostics, createType bool, data *VzTSubjResourceModel, tagAnnotationPlan, tagAnnotationState []TagAnnotationVzTSubjResourceModel, tagTagPlan, tagTagState []TagTagVzTSubjResourceModel, vzRsDenyRulePlan, vzRsDenyRuleState []VzRsDenyRuleVzTSubjResourceModel) *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 := getVzTSubjTagAnnotationChildPayloads(ctx, diags, data, tagAnnotationPlan, tagAnnotationState)
	if TagAnnotationchildPayloads == nil {
		return nil
	}
	childPayloads = append(childPayloads, TagAnnotationchildPayloads...)

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

	VzRsDenyRulechildPayloads := getVzTSubjVzRsDenyRuleChildPayloads(ctx, diags, data, vzRsDenyRulePlan, vzRsDenyRuleState)
	if VzRsDenyRulechildPayloads == nil {
		return nil
	}
	childPayloads = append(childPayloads, VzRsDenyRulechildPayloads...)

	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()
	}
	payload, err := json.Marshal(map[string]interface{}{"vzTSubj": 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
}
