package image

import (
	"encoding/json"
	"strconv"

	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	log "github.com/sirupsen/logrus"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
)

func flattenImage(d *schema.ResourceData, img *image.RecordImage) {
	cdPresentedTo, _ := json.Marshal(img.CdPresentedTo)

	log.Debugf("flattenImageID %d", img.ID)
	d.Set("image_id", img.ID)
	d.Set("unc_path", img.UNCPath)
	d.Set("account_id", img.AccountID)
	d.Set("acl", flattenAcl(img.ACL))
	d.Set("architecture", img.Architecture)
	d.Set("boot_type", img.BootType)
	d.Set("bootable", img.Bootable)
	d.Set("computeci_id", img.ComputeCIID)
	d.Set("cd_presented_to", string(cdPresentedTo))
	d.Set("deleted_time", img.DeletedTime)
	d.Set("desc", img.Description)
	d.Set("drivers", img.Drivers)
	d.Set("enabled", img.Enabled)
	d.Set("gid", img.GID)
	d.Set("guid", img.GUID)
	d.Set("history", flattenHistory(img.History))
	d.Set("hot_resize", img.HotResize)
	d.Set("independent", img.Independent)
	d.Set("last_modified", img.LastModified)
	d.Set("link_to", img.LinkTo)
	d.Set("links_to", img.LinksTo)
	d.Set("milestones", img.Milestones)
	d.Set("name", img.Name)
	d.Set("network_interface_naming", img.NetworkInterfaceNaming)
	d.Set("password", img.Password)
	d.Set("pool_name", img.Pool)
	d.Set("present_to", img.PresentTo)
	d.Set("provider_name", img.ProviderName)
	d.Set("purge_attempts", img.PurgeAttempts)
	d.Set("reference_id", img.ReferenceID)
	d.Set("res_id", img.ResID)
	d.Set("res_name", img.ResName)
	d.Set("rescuecd", img.RescueCD)
	d.Set("sep_id", img.SEPID)
	d.Set("shared_with", img.SharedWith)
	d.Set("size", img.Size)
	d.Set("snapshot_id", img.SnapshotID)
	d.Set("status", img.Status)
	d.Set("storage_policy_id", img.StoragePolicyID)
	d.Set("tech_status", img.TechStatus)
	d.Set("to_clean", img.ToClean)
	d.Set("target_ids", img.LinksTo)
	d.Set("image_type", img.Type)
	d.Set("url", img.URL)
	d.Set("username", img.Username)
	d.Set("version", img.Version)
}

func flattenAcl(acl image.ListACL) []map[string]interface{} {
	res := make([]map[string]interface{}, 0, len(acl))
	for _, val := range acl {
		temp := map[string]interface{}{
			"explicit":      val.Explicit,
			"guid":          val.GUID,
			"right":         val.Right,
			"status":        val.Status,
			"type":          val.Type,
			"user_group_id": val.UserGroupID,
		}
		res = append(res, temp)
	}
	return res
}

func flattenHistory(history image.ListHistory) []map[string]interface{} {
	temp := make([]map[string]interface{}, 0, len(history))
	for _, item := range history {
		t := map[string]interface{}{
			"id":        item.ID,
			"guid":      item.GUID,
			"timestamp": item.Timestamp,
		}
		temp = append(temp, t)
	}
	return temp
}

func flattenImageList(il *image.ListImages) []map[string]interface{} {
	log.Debug("flattenImageList")
	res := make([]map[string]interface{}, 0, len(il.Data))
	for _, item := range il.Data {
		cdPresentedTo, _ := json.Marshal(item.CdPresentedTo)

		temp := map[string]interface{}{
			"image_id":                 item.ID,
			"unc_path":                 item.UNCPath,
			"account_id":               item.AccountID,
			"acl":                      flattenAcl(item.ACL),
			"architecture":             item.Architecture,
			"boot_type":                item.BootType,
			"bootable":                 item.Bootable,
			"computeci_id":             item.ComputeCIID,
			"cd_presented_to":          string(cdPresentedTo),
			"deleted_time":             item.DeletedTime,
			"desc":                     item.Description,
			"drivers":                  item.Drivers,
			"enabled":                  item.Enabled,
			"gid":                      item.GID,
			"guid":                     item.GUID,
			"history":                  flattenHistory(item.History),
			"hot_resize":               item.HotResize,
			"independent":              item.Independent,
			"last_modified":            item.LastModified,
			"link_to":                  item.LinkTo,
			"links_to":                 item.LinksTo,
			"milestones":               item.Milestones,
			"name":                     item.Name,
			"network_interface_naming": item.NetworkInterfaceNaming,
			"password":                 item.Password,
			"pool_name":                item.Pool,
			"present_to":               item.PresentTo,
			"provider_name":            item.ProviderName,
			"purge_attempts":           item.PurgeAttempts,
			"reference_id":             item.ReferenceID,
			"res_id":                   item.ResID,
			"res_name":                 item.ResName,
			"rescuecd":                 item.RescueCD,
			"sep_id":                   item.SEPID,
			"shared_with":              item.SharedWith,
			"size":                     item.Size,
			"snapshot_id":              item.SnapshotID,
			"status":                   item.Status,
			"storage_policy_id":        item.StoragePolicyID,
			"tech_status":              item.TechStatus,
			"to_clean":                 item.ToClean,
			"image_type":               item.Type,
			"url":                      item.URL,
			"username":                 item.Username,
			"version":                  item.Version,
			"virtual":                  item.Virtual,
		}
		res = append(res, temp)
	}
	return res
}

func flattenEco(m interface{}) string {
	log.Debug("flattenEco")
	output := ""
	switch d := m.(type) {
	case string:
		output = d
	case int:
		output = strconv.Itoa(d)
	case int64:
		output = strconv.FormatInt(d, 10)
	case float64:
		output = strconv.FormatInt(int64(d), 10)
	default:
	}
	return output
}

func flattenPackages(pg image.Packages) []map[string]interface{} {
	log.Debug("flattenPackages")
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"libvirt_bin":        flattenLibvirtBin(pg),
		"libvirt_daemon":     flattenLibvirtDaemon(pg),
		"lvm2_lockd":         flattenLvm2Lockd(pg),
		"openvswitch_common": flattenOpenvswitchCommon(pg),
		"openvswitch_switch": flattenOpenvswitchSwitch(pg),
		"qemu_system_x86":    flattenQemuSystemX86(pg),
		"sanlock":            flattenSanlock(pg),
	}
	res = append(res, temp)
	return res
}

func flattenLibvirtBin(lb image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": lb.LibvirtBin.InstalledSize,
		"ver":            lb.LibvirtBin.Ver,
	}
	res = append(res, temp)
	return res
}

func flattenLibvirtDaemon(ld image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": ld.LibvirtDaemon.InstalledSize,
		"ver":            ld.LibvirtDaemon.Ver,
	}
	res = append(res, temp)
	return res
}

func flattenLvm2Lockd(ll image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": ll.Lvm2Lockd.InstalledSize,
		"ver":            ll.Lvm2Lockd.Ver,
	}
	res = append(res, temp)
	return res
}

func flattenOpenvswitchCommon(oc image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": oc.OpenvswitchCommon.InstalledSize,
		"ver":            oc.OpenvswitchCommon.Ver,
	}
	res = append(res, temp)
	return res
}

func flattenOpenvswitchSwitch(os image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": os.OpenvswitchSwitch.InstalledSize,
		"ver":            os.OpenvswitchSwitch.Ver,
	}
	res = append(res, temp)
	return res
}

func flattenQemuSystemX86(qs image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": qs.QemuSystemX86.InstalledSize,
		"ver":            qs.QemuSystemX86.Ver,
	}
	res = append(res, temp)
	return res
}

func flattenSanlock(sl image.Packages) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"installed_size": sl.Sanlock.InstalledSize,
		"ver":            sl.Sanlock.Ver,
	}
	res = append(res, temp)
	return res
}
