package mashup

import (
	"fmt"

	clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
	"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/factory/reg"
	"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
	cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
)

func init() {
	reg.RegisterBuilder[*cortypes.MashupStorageType](func(detail *clitypes.UserSpaceDetail) types.StorageBuilder {
		return &builder{
			detail: detail,
		}
	})
}

type builder struct {
	detail *clitypes.UserSpaceDetail
}

func (b *builder) FeatureDesc() types.FeatureDesc {
	stgType := b.detail.Storage.Type.(*cortypes.MashupStorageType)
	cred, ok := b.detail.UserSpace.Credential.(*cortypes.MashupCred)
	if !ok {
		return types.FeatureDesc{}
	}

	newDetail := *b.detail
	newDetail.Storage.Type = stgType.Store
	newDetail.UserSpace.Credential = cred.Store

	blder := reg.GetBuilderInternal(&newDetail)
	return blder.FeatureDesc()
}

func (b *builder) CreateShardStore() (types.ShardStore, error) {
	stgType := b.detail.Storage.Type.(*cortypes.MashupStorageType)
	cred, ok := b.detail.UserSpace.Credential.(*cortypes.MashupCred)
	if !ok {
		return nil, fmt.Errorf("invalid storage credential type %T for mashup storage", b.detail.UserSpace.Credential)
	}

	newDetail := *b.detail
	newDetail.Storage.Type = stgType.Store
	newDetail.UserSpace.Credential = cred.Store

	blder := reg.GetBuilderInternal(&newDetail)
	return blder.CreateShardStore()
}

func (b *builder) CreatePublicStore() (types.PublicStore, error) {
	stgType := b.detail.Storage.Type.(*cortypes.MashupStorageType)
	cred, ok := b.detail.UserSpace.Credential.(*cortypes.MashupCred)
	if !ok {
		return nil, fmt.Errorf("invalid storage credential type %T for mashup storage", b.detail.UserSpace.Credential)
	}

	newDetail := *b.detail
	newDetail.Storage.Type = stgType.Store
	newDetail.UserSpace.Credential = cred.Store

	blder := reg.GetBuilderInternal(&newDetail)
	return blder.CreatePublicStore()
}

func (b *builder) CreateMultiparter() (types.Multiparter, error) {
	stgType := b.detail.Storage.Type.(*cortypes.MashupStorageType)
	cred, ok := b.detail.UserSpace.Credential.(*cortypes.MashupCred)
	if !ok {
		return nil, fmt.Errorf("invalid storage credential type %T for mashup storage", b.detail.UserSpace.Credential)
	}

	newDetail := *b.detail
	newDetail.Storage.Type = stgType.Feature
	newDetail.UserSpace.Credential = cred.Feature

	blder := reg.GetBuilderInternal(&newDetail)
	return blder.CreateMultiparter()
}

func (b *builder) CreateS2STransfer() (types.S2STransfer, error) {
	stgType := b.detail.Storage.Type.(*cortypes.MashupStorageType)
	cred, ok := b.detail.UserSpace.Credential.(*cortypes.MashupCred)
	if !ok {
		return nil, fmt.Errorf("invalid storage credential type %T for mashup storage", b.detail.UserSpace.Credential)
	}

	newDetail := *b.detail
	newDetail.Storage.Type = stgType.Feature
	newDetail.UserSpace.Credential = cred.Feature

	blder := reg.GetBuilderInternal(&newDetail)
	return blder.CreateS2STransfer()
}

func (b *builder) CreateECMultiplier() (types.ECMultiplier, error) {
	stgType := b.detail.Storage.Type.(*cortypes.MashupStorageType)
	cred, ok := b.detail.UserSpace.Credential.(*cortypes.MashupCred)
	if !ok {
		return nil, fmt.Errorf("invalid storage credential type %T for mashup storage", b.detail.UserSpace.Credential)
	}

	newDetail := *b.detail
	newDetail.Storage.Type = stgType.Feature
	newDetail.UserSpace.Credential = cred.Feature

	blder := reg.GetBuilderInternal(&newDetail)
	return blder.CreateECMultiplier()
}
