package defaultsecuritypolicy

import (
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/defsecpolicies"
)

func flattenDefaultSecurityPolicyList(policyList *defsecpolicies.SecurityPoliciesList) []map[string]interface{} {
	if policyList == nil {
		return []map[string]interface{}{}
	}
	res := make([]map[string]interface{}, 0, len(policyList.Policies))
	for _, v := range policyList.Policies {
		temp := map[string]interface{}{
			"access_group_id":           v.AccessGroupID,
			"created_at":                v.CreatedAt,
			"default_acl_drop":          v.DefaultACLDrop,
			"default_open_session_drop": v.DefaultOpenSessionDrop,
			"description":               v.Description,
			"display_name":              v.DisplayName,
			"id":                        v.ID,
			"security_rules":            flattenSecurityRules(v.SecurityRules),
			"locked_at":                 v.LockedAt,
			"status":                    flattenStatus(v.Status),
			"version_id":                int(v.VersionID),
		}
		res = append(res, temp)
	}
	return res
}

func flattenSecurityRules(rules []defsecpolicies.SecurityRule) []map[string]interface{} {
	if rules == nil {
		return []map[string]interface{}{}
	}
	res := make([]map[string]interface{}, 0, len(rules))
	for _, v := range rules {
		temp := map[string]interface{}{
			"access_group_id":        v.AccessGroupID,
			"action":                 v.Action,
			"description":            v.Description,
			"destination_net_object": flattenNetObject(v.DestinationNetObject),
			"direction":              v.Direction,
			"display_name":           v.DisplayName,
			"enabled":                v.Enabled,
			"filter":                 flattenFilter(v.Filter),
			"id":                     v.ID,
			"log_enabled":            v.LogEnabled,
			"log_name":               v.LogName,
			"log_severity":           v.LogSeverity,
			"priority":               v.Priority,
			"security_policy_id":     v.SecurityPolicyID,
			"source_net_object":      flattenNetObject(v.SourceNetObject),
			"statistics_enabled":     v.StatisticsEnabled,
			"version_id":             int(v.VersionID),
		}
		res = append(res, temp)
	}
	return res
}

func flattenNetObject(netObj defsecpolicies.NetObject) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"display_name":        netObj.DisplayName,
		"net_address_pool_id": netObj.NetAddressPoolID,
		"net_object_group_id": netObj.NetObjectGroupID,
	}
	res = append(res, temp)
	return res
}

func flattenFilter(filter defsecpolicies.Filter) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"filters": flattenFilterParams(filter.Filters),
		"name":    filter.Name,
	}
	res = append(res, temp)
	return res
}

func flattenFilterParams(params defsecpolicies.FilterParams) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"all":                  params.All,
		"arp":                  params.ARP,
		"dhcp":                 params.DHCP,
		"expression":           params.Expression,
		"icmp":                 params.ICMP,
		"ip":                   params.IP,
		"ip_v4":                params.IPv4,
		"ip_v6":                params.IPv6,
		"keep_opened_sessions": params.KeepOpenedSessions,
		"nd":                   params.ND,
		"tcp":                  params.TCP,
		"tcp_dst_ports":        params.TCPDstPorts,
		"udp":                  params.UDP,
		"udp_dst_ports":        params.UDPDstPorts,
	}
	res = append(res, temp)
	return res
}

func flattenStatus(status defsecpolicies.Status) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"common":      status.Common,
		"hypervisors": flattenHypervisorStatuses(status.Hypervisors),
	}
	res = append(res, temp)
	return res
}

func flattenHypervisorStatuses(hypervisors []defsecpolicies.HypervisorStatus) []map[string]interface{} {
	if hypervisors == nil {
		return []map[string]interface{}{}
	}
	res := make([]map[string]interface{}, 0, len(hypervisors))
	for _, v := range hypervisors {
		temp := map[string]interface{}{
			"status":            v.Status,
			"name":              v.Name,
			"display_name":      v.DisplayName,
			"hypervisor_status": v.HypervisorStatus,
			"synced_at":         v.SyncedAt,
		}
		res = append(res, temp)
	}
	return res
}
