package models

import (
	"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
	"github.com/hashicorp/terraform-plugin-framework/attr"
	"github.com/hashicorp/terraform-plugin-framework/types"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
)

type ResourceVINSModel struct {
	// required fields
	Name      types.String `tfsdk:"name"`
	RGID      types.Int64  `tfsdk:"rg_id"`
	AccountID types.Int64  `tfsdk:"account_id"`

	// optional fields
	IPCIDR             types.String `tfsdk:"ipcidr"`
	PreReservationsNum types.Int64  `tfsdk:"pre_reservations_num"`
	Description        types.String `tfsdk:"description"`
	GID                types.Int64  `tfsdk:"gid"`
	DNS                types.Set    `tfsdk:"dns"`

	Enable         types.Bool   `tfsdk:"enable"`
	Permanently    types.Bool   `tfsdk:"permanently"`
	Force          types.Bool   `tfsdk:"force"`
	Restore        types.Bool   `tfsdk:"restore"`
	VnfdevStart    types.Bool   `tfsdk:"vnfdev_start"`
	VnfdevReset    types.Bool   `tfsdk:"vnfdev_reset"`
	VnfdevRestart  types.Bool   `tfsdk:"vnfdev_restart"`
	VnfdevRedeploy types.Bool   `tfsdk:"vnfdev_redeploy"`
	DefaultQOS     types.Object `tfsdk:"default_qos"`

	ExtNet   types.Object   `tfsdk:"ext_net"`
	IP       types.List     `tfsdk:"ip"`
	NatRule  types.List     `tfsdk:"nat_rule"`
	Timeouts timeouts.Value `tfsdk:"timeouts"`

	// response fields
	VinsID      types.Int64  `tfsdk:"vins_id"`
	Id          types.String `tfsdk:"id"`
	LastUpdated types.String `tfsdk:"last_updated"`
	VNFDev      types.Object `tfsdk:"vnf_dev"`
	AccountName types.String `tfsdk:"account_name"`
	CreatedBy   types.String `tfsdk:"created_by"`
	CreatedTime types.Int64  `tfsdk:"created_time"`
	DefaultGW   types.String `tfsdk:"default_gw"`
	DeletedBy   types.String `tfsdk:"deleted_by"`
	DeletedTime types.Int64  `tfsdk:"deleted_time"`
	GUID        types.Int64  `tfsdk:"guid"`
	LockStatus  types.String `tfsdk:"lock_status"`
	ManagerID   types.Int64  `tfsdk:"manager_id"`
	ManagerType types.String `tfsdk:"manager_type"`
	Milestones  types.Int64  `tfsdk:"milestones"`
	NetMask     types.Int64  `tfsdk:"net_mask"`
	Network     types.String `tfsdk:"network"`
	Redundant   types.Bool   `tfsdk:"redundant"`
	RGName      types.String `tfsdk:"rg_name"`
	SecVNFDevID types.Int64  `tfsdk:"sec_vnf_dev_id"`
	Status      types.String `tfsdk:"status"`
	UpdatedBy   types.String `tfsdk:"updated_by"`
	UpdatedTime types.Int64  `tfsdk:"updated_time"`
	UserManaged types.Bool   `tfsdk:"user_managed"`
	VNFs        types.Object `tfsdk:"vnfs"`
	VXLANID     types.Int64  `tfsdk:"vxlan_id"`
}

type ExtNetModel struct {
	ExtNetID types.Int64  `tfsdk:"ext_net_id"`
	ExtNetIP types.String `tfsdk:"ext_net_ip"`
}

type IPModel struct {
	Type      types.String `tfsdk:"type"`
	IPAddr    types.String `tfsdk:"ip_addr"`
	MacAddr   types.String `tfsdk:"mac_addr"`
	ComputeID types.Int64  `tfsdk:"compute_id"`
}

type NatRuleResourceModel struct {
	IntIP        types.String `tfsdk:"int_ip"`
	IntPort      types.Int64  `tfsdk:"int_port"`
	ExtPortStart types.Int64  `tfsdk:"ext_port_start"`
	ExtPortEnd   types.Int64  `tfsdk:"ext_port_end"`
	Proto        types.String `tfsdk:"proto"`
	RuleID       types.Int64  `tfsdk:"rule_id"`
}

var ItemNatRuleResource = map[string]attr.Type{
	"int_ip":         types.StringType,
	"int_port":       types.Int64Type,
	"ext_port_start": types.Int64Type,
	"ext_port_end":   types.Int64Type,
	"proto":          types.StringType,
	"rule_id":        types.Int64Type,
}

// Contains returns true if NatRuleResourceModel contains n as an element. Otherwise it returns false.
func (n *NatRuleResourceModel) Contains(natRuleList []NatRuleResourceModel) bool {
	for _, natRuleElem := range natRuleList {
		if n.IntIP.Equal(natRuleElem.IntIP) &&
			n.IntPort.Equal(natRuleElem.IntPort) &&
			n.ExtPortStart.Equal(natRuleElem.ExtPortStart) {
			return true
		}
	}
	return false
}

// GetNatRule returns nat_rule from the platform equivalent to NatRuleResourceModel. If the rule doesn't exist it returns nil.
func (n *NatRuleResourceModel) GetNatRule(rules vins.ListNATRule) *vins.ItemNATRule {
	for _, rule := range rules {
		if n.IntIP.Equal(types.StringValue(rule.LocalIP)) &&
			n.ExtPortStart.Equal(types.Int64Value(int64(rule.PublicPortStart))) {
			return &rule
		}
	}
	return nil
}

// Contains returns true if IPModel contains i as an element. Otherwise it returns false.
func (i *IPModel) Contains(ipList []IPModel) bool {
	for _, ipElem := range ipList {
		if i.IPAddr.Equal(ipElem.IPAddr) {
			return true
		}
	}
	return false
}
