// Code generated by "gen/generator.go"; DO NOT EDIT.

package provider

import (
	"context"
	"fmt"

	"github.com/hashicorp/terraform-plugin-framework/types"
	"github.com/tidwall/gjson"
	"github.com/tidwall/sjson"
)

type DeviceACL struct {
	Id            types.String         `tfsdk:"id"`
	Version       types.Int64          `tfsdk:"version"`
	Type          types.String         `tfsdk:"type"`
	Name          types.String         `tfsdk:"name"`
	Description   types.String         `tfsdk:"description"`
	DefaultAction types.String         `tfsdk:"default_action"`
	Sequences     []DeviceACLSequences `tfsdk:"sequences"`
}

type DeviceACLSequences struct {
	Id            types.Int64                       `tfsdk:"id"`
	IpType        types.String                      `tfsdk:"ip_type"`
	Name          types.String                      `tfsdk:"name"`
	BaseAction    types.String                      `tfsdk:"base_action"`
	MatchEntries  []DeviceACLSequencesMatchEntries  `tfsdk:"match_entries"`
	ActionEntries []DeviceACLSequencesActionEntries `tfsdk:"action_entries"`
}

type DeviceACLSequencesMatchEntries struct {
	Type                             types.String `tfsdk:"type"`
	SourceIp                         types.String `tfsdk:"source_ip"`
	DestinationIp                    types.String `tfsdk:"destination_ip"`
	SourcePort                       types.Int64  `tfsdk:"source_port"`
	DestinationPort                  types.Int64  `tfsdk:"destination_port"`
	SourceDataPrefixListId           types.String `tfsdk:"source_data_prefix_list_id"`
	SourceDataPrefixListVersion      types.Int64  `tfsdk:"source_data_prefix_list_version"`
	DestinationDataPrefixListId      types.String `tfsdk:"destination_data_prefix_list_id"`
	DestinationDataPrefixListVersion types.Int64  `tfsdk:"destination_data_prefix_list_version"`
}
type DeviceACLSequencesActionEntries struct {
	Type        types.String `tfsdk:"type"`
	CounterName types.String `tfsdk:"counter_name"`
}

func (data DeviceACL) getType() string {
	return "deviceAccessPolicy"
}

func (data DeviceACL) toBody(ctx context.Context) string {
	body, _ := sjson.Set("", "name", data.Name.ValueString())
	body, _ = sjson.Set(body, "description", data.Description.ValueString())
	body, _ = sjson.Set(body, "type", "deviceAccessPolicy")
	path := ""
	if !data.DefaultAction.IsNull() {
		body, _ = sjson.Set(body, path+"defaultAction.type", data.DefaultAction.ValueString())
	}
	if len(data.Sequences) > 0 {
		body, _ = sjson.Set(body, path+"sequences", []interface{}{})
		for _, item := range data.Sequences {
			itemBody := ""
			if !item.Id.IsNull() {
				itemBody, _ = sjson.Set(itemBody, "sequenceId", item.Id.ValueInt64())
			}
			if !item.IpType.IsNull() {
				itemBody, _ = sjson.Set(itemBody, "sequenceIpType", item.IpType.ValueString())
			}
			if !item.Name.IsNull() {
				itemBody, _ = sjson.Set(itemBody, "sequenceName", item.Name.ValueString())
			}
			itemBody, _ = sjson.Set(itemBody, "sequenceType", "deviceaccesspolicy")
			if !item.BaseAction.IsNull() {
				itemBody, _ = sjson.Set(itemBody, "baseAction", item.BaseAction.ValueString())
			}
			if len(item.MatchEntries) > 0 {
				itemBody, _ = sjson.Set(itemBody, "match.entries", []interface{}{})
				for _, childItem := range item.MatchEntries {
					itemChildBody := ""
					if !childItem.Type.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "field", childItem.Type.ValueString())
					}
					if !childItem.SourceIp.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "value", childItem.SourceIp.ValueString())
					}
					if !childItem.DestinationIp.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "value", childItem.DestinationIp.ValueString())
					}
					if !childItem.SourcePort.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "value", fmt.Sprint(childItem.SourcePort.ValueInt64()))
					}
					if !childItem.DestinationPort.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "value", fmt.Sprint(childItem.DestinationPort.ValueInt64()))
					}
					if !childItem.SourceDataPrefixListId.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "ref", childItem.SourceDataPrefixListId.ValueString())
					}
					if !childItem.DestinationDataPrefixListId.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "ref", childItem.DestinationDataPrefixListId.ValueString())
					}
					itemBody, _ = sjson.SetRaw(itemBody, "match.entries.-1", itemChildBody)
				}
			}
			if len(item.ActionEntries) > 0 {
				itemBody, _ = sjson.Set(itemBody, "actions", []interface{}{})
				for _, childItem := range item.ActionEntries {
					itemChildBody := ""
					if !childItem.Type.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "type", childItem.Type.ValueString())
					}
					if !childItem.CounterName.IsNull() {
						itemChildBody, _ = sjson.Set(itemChildBody, "parameter", childItem.CounterName.ValueString())
					}
					itemBody, _ = sjson.SetRaw(itemBody, "actions.-1", itemChildBody)
				}
			}
			body, _ = sjson.SetRaw(body, path+"sequences.-1", itemBody)
		}
	}
	return body
}

func (data *DeviceACL) fromBody(ctx context.Context, res gjson.Result) {
	if value := res.Get("name"); value.Exists() {
		data.Name = types.StringValue(value.String())
	} else {
		data.Name = types.StringNull()
	}
	if value := res.Get("description"); value.Exists() {
		data.Description = types.StringValue(value.String())
	} else {
		data.Description = types.StringNull()
	}
	if value := res.Get("type"); value.Exists() {
		data.Type = types.StringValue(value.String())
	} else {
		data.Type = types.StringNull()
	}
	path := ""
	if value := res.Get(path + "defaultAction.type"); value.Exists() {
		data.DefaultAction = types.StringValue(value.String())
	} else {
		data.DefaultAction = types.StringNull()
	}
	if value := res.Get(path + "sequences"); value.Exists() {
		data.Sequences = make([]DeviceACLSequences, 0)
		value.ForEach(func(k, v gjson.Result) bool {
			item := DeviceACLSequences{}
			if cValue := v.Get("sequenceId"); cValue.Exists() {
				item.Id = types.Int64Value(cValue.Int())
			} else {
				item.Id = types.Int64Null()
			}
			if cValue := v.Get("sequenceIpType"); cValue.Exists() {
				item.IpType = types.StringValue(cValue.String())
			} else {
				item.IpType = types.StringNull()
			}
			if cValue := v.Get("sequenceName"); cValue.Exists() {
				item.Name = types.StringValue(cValue.String())
			} else {
				item.Name = types.StringNull()
			}
			if cValue := v.Get("baseAction"); cValue.Exists() {
				item.BaseAction = types.StringValue(cValue.String())
			} else {
				item.BaseAction = types.StringNull()
			}
			if cValue := v.Get("match.entries"); cValue.Exists() {
				item.MatchEntries = make([]DeviceACLSequencesMatchEntries, 0)
				cValue.ForEach(func(ck, cv gjson.Result) bool {
					cItem := DeviceACLSequencesMatchEntries{}
					if ccValue := cv.Get("field"); ccValue.Exists() {
						cItem.Type = types.StringValue(ccValue.String())
					} else {
						cItem.Type = types.StringNull()
					}
					if ccValue := cv.Get("value"); cItem.Type.ValueString() == "sourceIp" && ccValue.Exists() {
						cItem.SourceIp = types.StringValue(ccValue.String())
					} else {
						cItem.SourceIp = types.StringNull()
					}
					if ccValue := cv.Get("value"); cItem.Type.ValueString() == "destinationIp" && ccValue.Exists() {
						cItem.DestinationIp = types.StringValue(ccValue.String())
					} else {
						cItem.DestinationIp = types.StringNull()
					}
					if ccValue := cv.Get("value"); cItem.Type.ValueString() == "sourcePort" && ccValue.Exists() {
						cItem.SourcePort = types.Int64Value(ccValue.Int())
					} else {
						cItem.SourcePort = types.Int64Null()
					}
					if ccValue := cv.Get("value"); cItem.Type.ValueString() == "destinationPort" && ccValue.Exists() {
						cItem.DestinationPort = types.Int64Value(ccValue.Int())
					} else {
						cItem.DestinationPort = types.Int64Null()
					}
					if ccValue := cv.Get("ref"); cItem.Type.ValueString() == "sourceDataPrefixList" && ccValue.Exists() {
						cItem.SourceDataPrefixListId = types.StringValue(ccValue.String())
					} else {
						cItem.SourceDataPrefixListId = types.StringNull()
					}
					if ccValue := cv.Get("ref"); cItem.Type.ValueString() == "destinationDataPrefixList" && ccValue.Exists() {
						cItem.DestinationDataPrefixListId = types.StringValue(ccValue.String())
					} else {
						cItem.DestinationDataPrefixListId = types.StringNull()
					}
					item.MatchEntries = append(item.MatchEntries, cItem)
					return true
				})
			}
			if cValue := v.Get("actions"); cValue.Exists() {
				item.ActionEntries = make([]DeviceACLSequencesActionEntries, 0)
				cValue.ForEach(func(ck, cv gjson.Result) bool {
					cItem := DeviceACLSequencesActionEntries{}
					if ccValue := cv.Get("type"); ccValue.Exists() {
						cItem.Type = types.StringValue(ccValue.String())
					} else {
						cItem.Type = types.StringNull()
					}
					if ccValue := cv.Get("parameter"); ccValue.Exists() {
						cItem.CounterName = types.StringValue(ccValue.String())
					} else {
						cItem.CounterName = types.StringNull()
					}
					item.ActionEntries = append(item.ActionEntries, cItem)
					return true
				})
			}
			data.Sequences = append(data.Sequences, item)
			return true
		})
	}
}

func (data *DeviceACL) hasChanges(ctx context.Context, state *DeviceACL) bool {
	hasChanges := false
	if !data.Name.Equal(state.Name) {
		hasChanges = true
	}
	if !data.Description.Equal(state.Description) {
		hasChanges = true
	}
	if !data.DefaultAction.Equal(state.DefaultAction) {
		hasChanges = true
	}
	if len(data.Sequences) != len(state.Sequences) {
		hasChanges = true
	} else {
		for i := range data.Sequences {
			if !data.Sequences[i].Id.Equal(state.Sequences[i].Id) {
				hasChanges = true
			}
			if !data.Sequences[i].IpType.Equal(state.Sequences[i].IpType) {
				hasChanges = true
			}
			if !data.Sequences[i].Name.Equal(state.Sequences[i].Name) {
				hasChanges = true
			}
			if !data.Sequences[i].BaseAction.Equal(state.Sequences[i].BaseAction) {
				hasChanges = true
			}
			if len(data.Sequences[i].MatchEntries) != len(state.Sequences[i].MatchEntries) {
				hasChanges = true
			} else {
				for ii := range data.Sequences[i].MatchEntries {
					if !data.Sequences[i].MatchEntries[ii].Type.Equal(state.Sequences[i].MatchEntries[ii].Type) {
						hasChanges = true
					}
					if !data.Sequences[i].MatchEntries[ii].SourceIp.Equal(state.Sequences[i].MatchEntries[ii].SourceIp) {
						hasChanges = true
					}
					if !data.Sequences[i].MatchEntries[ii].DestinationIp.Equal(state.Sequences[i].MatchEntries[ii].DestinationIp) {
						hasChanges = true
					}
					if !data.Sequences[i].MatchEntries[ii].SourcePort.Equal(state.Sequences[i].MatchEntries[ii].SourcePort) {
						hasChanges = true
					}
					if !data.Sequences[i].MatchEntries[ii].DestinationPort.Equal(state.Sequences[i].MatchEntries[ii].DestinationPort) {
						hasChanges = true
					}
					if !data.Sequences[i].MatchEntries[ii].SourceDataPrefixListId.Equal(state.Sequences[i].MatchEntries[ii].SourceDataPrefixListId) {
						hasChanges = true
					}
					if !data.Sequences[i].MatchEntries[ii].DestinationDataPrefixListId.Equal(state.Sequences[i].MatchEntries[ii].DestinationDataPrefixListId) {
						hasChanges = true
					}
				}
			}
			if len(data.Sequences[i].ActionEntries) != len(state.Sequences[i].ActionEntries) {
				hasChanges = true
			} else {
				for ii := range data.Sequences[i].ActionEntries {
					if !data.Sequences[i].ActionEntries[ii].Type.Equal(state.Sequences[i].ActionEntries[ii].Type) {
						hasChanges = true
					}
					if !data.Sequences[i].ActionEntries[ii].CounterName.Equal(state.Sequences[i].ActionEntries[ii].CounterName) {
						hasChanges = true
					}
				}
			}
		}
	}
	return hasChanges
}

func (data *DeviceACL) getMatchSourceDataPrefixListVersion(ctx context.Context, name string, id int64) types.Int64 {
	for _, item := range data.Sequences {
		if item.Name.ValueString() == name && item.Id.ValueInt64() == id {
			for _, cItem := range item.MatchEntries {
				if cItem.Type.ValueString() == "sourceDataPrefixList" {
					return cItem.SourceDataPrefixListVersion
				}
			}
		}
	}
	return types.Int64Null()
}

func (data *DeviceACL) getMatchDestinationDataPrefixListVersion(ctx context.Context, name string, id int64) types.Int64 {
	for _, item := range data.Sequences {
		if item.Name.ValueString() == name && item.Id.ValueInt64() == id {
			for _, cItem := range item.MatchEntries {
				if cItem.Type.ValueString() == "destinationDataPrefixList" {
					return cItem.DestinationDataPrefixListVersion
				}
			}
		}
	}
	return types.Int64Null()
}

func (data *DeviceACL) updateVersions(ctx context.Context, state DeviceACL) {
	for s := range data.Sequences {
		id := data.Sequences[s].Id.ValueInt64()
		name := data.Sequences[s].Name.ValueString()
		for m := range data.Sequences[s].MatchEntries {
			t := data.Sequences[s].MatchEntries[m].Type.ValueString()
			if t == "sourceDataPrefixList" {
				data.Sequences[s].MatchEntries[m].SourceDataPrefixListVersion = state.getMatchSourceDataPrefixListVersion(ctx, name, id)
			} else if t == "destinationDataPrefixList" {
				data.Sequences[s].MatchEntries[m].DestinationDataPrefixListVersion = state.getMatchDestinationDataPrefixListVersion(ctx, name, id)
			}
		}
	}
}
