// © Broadcom. All Rights Reserved.
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
// SPDX-License-Identifier: Apache-2.0

package object

import (
	"context"
	"encoding/json"

	"github.com/vmware/govmomi/vim25"
	"github.com/vmware/govmomi/vim25/methods"
	"github.com/vmware/govmomi/vim25/types"
)

type HostVsanInternalSystem struct {
	Common
}

func NewHostVsanInternalSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanInternalSystem {
	m := HostVsanInternalSystem{
		Common: NewCommon(c, ref),
	}

	return &m
}

// QueryVsanObjectUuidsByFilter returns vSAN DOM object uuids by filter.
func (m HostVsanInternalSystem) QueryVsanObjectUuidsByFilter(ctx context.Context, uuids []string, limit int32, version int32) ([]string, error) {
	req := types.QueryVsanObjectUuidsByFilter{
		This:    m.Reference(),
		Uuids:   uuids,
		Limit:   &limit,
		Version: version,
	}

	res, err := methods.QueryVsanObjectUuidsByFilter(ctx, m.Client(), &req)
	if err != nil {
		return nil, err
	}

	return res.Returnval, nil
}

type VsanObjExtAttrs struct {
	Type  string `json:"Object type"`
	Class string `json:"Object class"`
	Size  string `json:"Object size"`
	Path  string `json:"Object path"`
	Name  string `json:"User friendly name"`
}

func (a *VsanObjExtAttrs) DatastorePath(dir string) string {
	l := len(dir)
	path := a.Path

	if len(path) >= l {
		path = a.Path[l:]
	}

	if path != "" {
		return path
	}

	return a.Name // vmnamespace
}

// GetVsanObjExtAttrs is internal and intended for troubleshooting/debugging situations in the field.
// WARNING: This API can be slow because we do IOs (reads) to all the objects.
func (m HostVsanInternalSystem) GetVsanObjExtAttrs(ctx context.Context, uuids []string) (map[string]VsanObjExtAttrs, error) {
	req := types.GetVsanObjExtAttrs{
		This:  m.Reference(),
		Uuids: uuids,
	}

	res, err := methods.GetVsanObjExtAttrs(ctx, m.Client(), &req)
	if err != nil {
		return nil, err
	}

	var attrs map[string]VsanObjExtAttrs

	err = json.Unmarshal([]byte(res.Returnval), &attrs)

	return attrs, err
}

// DeleteVsanObjects is internal and intended for troubleshooting/debugging only.
// WARNING: This API can be slow because we do IOs to all the objects.
// DOM won't allow access to objects which have lost quorum. Such objects can be deleted with the optional "force" flag.
// These objects may however re-appear with quorum if the absent components come back (network partition gets resolved, etc.)
func (m HostVsanInternalSystem) DeleteVsanObjects(ctx context.Context, uuids []string, force *bool) ([]types.HostVsanInternalSystemDeleteVsanObjectsResult, error) {
	req := types.DeleteVsanObjects{
		This:  m.Reference(),
		Uuids: uuids,
		Force: force,
	}

	res, err := methods.DeleteVsanObjects(ctx, m.Client(), &req)
	if err != nil {
		return nil, err
	}

	return res.Returnval, nil
}
