package datamap

import (
	"fmt"
	"time"

	"gitlink.org.cn/cloudream/common/pkgs/types"
	"gitlink.org.cn/cloudream/common/utils/serder"
	clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
	cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
)

// 系统事件
type SysEvent struct {
	Timestamp time.Time      `json:"timestamp"`
	Source    SysEventSource `json:"source"`
	Body      SysEventBody   `json:"body"`
}

func (e *SysEvent) String() string {
	return fmt.Sprintf("%v [%v] %+v", e.Timestamp.Format("2006-01-02 15:04:05"), e.Source, e.Body)
}

// 事件源
type SysEventSource interface {
	GetSourceType() string
}

var _ = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[SysEventSource](
	(*SourceCoordinator)(nil),
	(*SourceHub)(nil),
	(*SourceClient)(nil),
)), "type")

type SourceCoordinator struct {
	serder.Metadata `union:"Coordinator"`
	Type            string `json:"type"`
}

func (s *SourceCoordinator) GetSourceType() string {
	return "Coordinator"
}

func (s *SourceCoordinator) OnUnionSerializing() {
	s.Type = s.GetSourceType()
}

func (s *SourceCoordinator) String() string {
	return "Coordinator"
}

type SourceHub struct {
	serder.Metadata `union:"Hub"`
	Type            string         `json:"type"`
	HubID           cortypes.HubID `json:"hubID"`
	HubName         string         `json:"hubName"`
}

func (s *SourceHub) GetSourceType() string {
	return "Hub"
}

func (s *SourceHub) OnUnionSerializing() {
	s.Type = s.GetSourceType()
}

func (s *SourceHub) String() string {
	return fmt.Sprintf("Hub(%d, %s)", s.HubID, s.HubName)
}

type SourceClient struct {
	serder.Metadata `union:"Client"`
	Type            string          `json:"type"`
	UserID          cortypes.UserID `json:"userID"`
}

func (s *SourceClient) GetSourceType() string {
	return "Client"
}

func (s *SourceClient) OnUnionSerializing() {
	s.Type = s.GetSourceType()
}

func (s *SourceClient) String() string {
	return fmt.Sprintf("Client(%d)", s.UserID)
}

// 事件体
type SysEventBody interface {
	GetBodyType() string
}

var _ = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[SysEventBody](
	// (*BodyNewHub)(nil),
	// (*BodyHubUpdated)(nil),
	// (*BodyHubDeleted)(nil),

	(*BodyNewUserSpace)(nil),
	(*BodyUserSpaceUpdated)(nil),
	(*BodyUserSpaceDeleted)(nil),

	// (*BodyStorageStats)(nil),
	// (*BodyHubTransferStats)(nil),
	// (*BodyHubStorageTransferStats)(nil),
	(*BodyBlockTransfer)(nil),
	(*BodyBlockDistribution)(nil),

	(*BodyNewOrUpdateObject)(nil),
	(*BodyObjectInfoUpdated)(nil),
	(*BodyObjectDeleted)(nil),

	(*BodyNewPackage)(nil),
	(*BodyPackageCloned)(nil),
	(*BodyPackageDeleted)(nil),

	(*BodyNewBucket)(nil),
	(*BodyBucketDeleted)(nil),
)), "type")

/*
// 新增Hub的事件
type BodyNewHub struct {
	serder.Metadata `union:"NewHub"`
	Type            string       `json:"type"`
	Info            cortypes.Hub `json:"info"`
}

func (b *BodyNewHub) GetBodyType() string {
	return "NewHub"
}

func (b *BodyNewHub) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Hub信息更新的事件
type BodyHubUpdated struct {
	serder.Metadata `union:"HubUpdated"`
	Type            string       `json:"type"`
	Info            cortypes.Hub `json:"info"`
}

func (b *BodyHubUpdated) GetBodyType() string {
	return "HubUpdated"
}

func (b *BodyHubUpdated) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Hub删除的事件
type BodyHubDeleted struct {
	serder.Metadata `union:"HubDeleted"`
	Type            string         `json:"type"`
	HubID           cortypes.HubID `json:"hubID"`
}

func (b *BodyHubDeleted) GetBodyType() string {
	return "HubDeleted"
}

func (b *BodyHubDeleted) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}
*/

// 新增Storage的事件
type BodyNewUserSpace struct {
	serder.Metadata `union:"NewUserSpace"`
	Info            clitypes.UserSpace `json:"info"`
	Type            string             `json:"type"`
}

func (b *BodyNewUserSpace) GetBodyType() string {
	return "NewUserSpace"
}

func (b *BodyNewUserSpace) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Storage信息更新的事件
type BodyUserSpaceUpdated struct {
	serder.Metadata `union:"UserSpaceUpdated"`
	Type            string             `json:"type"`
	Info            clitypes.UserSpace `json:"info"`
}

func (b *BodyUserSpaceUpdated) GetBodyType() string {
	return "UserSpaceUpdated"
}

func (b *BodyUserSpaceUpdated) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Storage删除的事件
type BodyUserSpaceDeleted struct {
	serder.Metadata `union:"UserSpaceDeleted"`
	Type            string               `json:"type"`
	UserSpaceID     clitypes.UserSpaceID `json:"userSpaceID"`
}

func (b *BodyUserSpaceDeleted) GetBodyType() string {
	return "UserSpaceDeleted"
}

func (b *BodyUserSpaceDeleted) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

/*
// Storage统计信息的事件
type BodyStorageStats struct {
	serder.Metadata `union:"StorageStats"`
	Type            string             `json:"type"`
	StorageID       clitypes.StorageID `json:"storageID"`
	DataCount       int64              `json:"dataCount"`
}

func (b *BodyStorageStats) GetBodyType() string {
	return "StorageStats"
}

func (b *BodyStorageStats) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Hub数据传输统计信息的事件
type BodyHubTransferStats struct {
	serder.Metadata `union:"HubTransferStats"`
	Type            string         `json:"type"`
	SourceHubID     cortypes.HubID `json:"sourceHubID"`
	TargetHubID     cortypes.HubID `json:"targetHubID"`
	Send            DataTrans      `json:"send"`
	StartTimestamp  time.Time      `json:"startTimestamp"`
	EndTimestamp    time.Time      `json:"endTimestamp"`
}

func (b *BodyHubTransferStats) GetBodyType() string {
	return "HubTransferStats"
}

func (b *BodyHubTransferStats) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

type DataTrans struct {
	TotalTransfer      int64 `json:"totalTransfer"`
	RequestCount       int64 `json:"requestCount"`
	FailedRequestCount int64 `json:"failedRequestCount"`
	AvgTransfer        int64 `json:"avgTransfer"`
	MaxTransfer        int64 `json:"maxTransfer"`
	MinTransfer        int64 `json:"minTransfer"`
}

// Hub和Storage数据传输统计信息的事件
type BodyHubStorageTransferStats struct {
	serder.Metadata `union:"HubStorageTransferStats"`
	Type            string             `json:"type"`
	HubID           cortypes.HubID     `json:"hubID"`
	StorageID       clitypes.StorageID `json:"storageID"`
	Send            DataTrans          `json:"send"`
	Receive         DataTrans          `json:"receive"`
	StartTimestamp  time.Time          `json:"startTimestamp"`
	EndTimestamp    time.Time          `json:"endTimestamp"`
}

func (b *BodyHubStorageTransferStats) GetBodyType() string {
	return "HubStorageTransferStats"
}

func (b *BodyHubStorageTransferStats) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}
*/

// 块传输的事件
type BodyBlockTransfer struct {
	serder.Metadata `union:"BlockTransfer"`
	Type            string             `json:"type"`
	ObjectID        clitypes.ObjectID  `json:"objectID"`
	PackageID       clitypes.PackageID `json:"packageID"`
	BlockChanges    []BlockChange      `json:"blockChanges"`
}

func (b *BodyBlockTransfer) GetBodyType() string {
	return "BlockTransfer"
}

func (b *BodyBlockTransfer) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// 块变化类型
type BlockChange interface {
	GetBlockChangeType() string
}

var _ = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[BlockChange](
	(*BlockChangeClone)(nil),
	(*BlockChangeDeleted)(nil),
	(*BlockChangeEnDecode)(nil),
)), "type")

const (
	BlockTypeRaw     = "Raw"
	BlockTypeEC      = "EC"
	BlockTypeSegment = "Segment"
)

type Block struct {
	BlockType   string               `json:"blockType"`
	Index       int                  `json:"index"`
	UserSpaceID clitypes.UserSpaceID `json:"userSpaceID"`
}
type DataTransfer struct {
	SourceUserSpaceID clitypes.UserSpaceID `json:"sourceUserSpaceID"`
	TargetUserSpaceID clitypes.UserSpaceID `json:"targetUserSpaceID"`
	TransferBytes     int64                `json:"transferBytes"`
}

type BlockChangeClone struct {
	serder.Metadata   `union:"Clone"`
	Type              string               `json:"type"`
	BlockType         string               `json:"blockType"`
	Index             int                  `json:"index"`
	SourceUserSpaceID clitypes.UserSpaceID `json:"sourceUserSpaceID"`
	TargetUserSpaceID clitypes.UserSpaceID `json:"targetUserSpaceID"`
	TransferBytes     int64                `json:"transferBytes"`
}

func (b *BlockChangeClone) GetBlockChangeType() string {
	return "Clone"
}

func (b *BlockChangeClone) OnUnionSerializing() {
	b.Type = b.GetBlockChangeType()
}

type BlockChangeDeleted struct {
	serder.Metadata `union:"Deleted"`
	Type            string               `json:"type"`
	Index           int                  `json:"index"`
	UserSpaceID     clitypes.UserSpaceID `json:"userSpaceID"`
}

func (b *BlockChangeDeleted) GetBlockChangeType() string {
	return "Deleted"
}

func (b *BlockChangeDeleted) OnUnionSerializing() {
	b.Type = b.GetBlockChangeType()
}

type BlockChangeEnDecode struct {
	serder.Metadata `union:"EnDecode"`
	Type            string         `json:"type"`
	SourceBlocks    []Block        `json:"sourceBlocks,omitempty"`
	TargetBlocks    []Block        `json:"targetBlocks,omitempty"`
	DataTransfers   []DataTransfer `json:"dataTransfers,omitempty"`
}

func (b *BlockChangeEnDecode) GetBlockChangeType() string {
	return "EnDecode"
}

func (b *BlockChangeEnDecode) OnUnionSerializing() {
	b.Type = b.GetBlockChangeType()
}

// 块分布的事件
type BodyBlockDistribution struct {
	serder.Metadata   `union:"BlockDistribution"`
	Type              string                        `json:"type"`
	ObjectID          clitypes.ObjectID             `json:"objectID"`
	PackageID         clitypes.PackageID            `json:"packageID"`
	Path              string                        `json:"path"`
	Size              int64                         `json:"size"`
	FileHash          clitypes.FileHash             `json:"fileHash"`
	FaultTolerance    float64                       `json:"faultTolerance"`
	Redundancy        float64                       `json:"redundancy"`
	AvgAccessCost     float64                       `json:"avgAccessCost"`
	BlockDistribution []BlockDistributionObjectInfo `json:"blockDistribution"`
	DataTransfers     []DataTransfer                `json:"dataTransfers"`
}

func (b *BodyBlockDistribution) GetBodyType() string {
	return "BlockDistribution"
}

func (b *BodyBlockDistribution) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

type BlockDistributionObjectInfo struct {
	BlockType   string               `json:"type"`
	Index       int                  `json:"index"`
	UserSpaceID clitypes.UserSpaceID `json:"userSpaceID"`
}

// 新增或者重新上传Object的事件
type BodyNewOrUpdateObject struct {
	serder.Metadata   `union:"NewOrUpdateObject"`
	Type              string                        `json:"type"`
	Info              clitypes.Object               `json:"info"`
	BlockDistribution []BlockDistributionObjectInfo `json:"blockDistribution"`
}

func (b *BodyNewOrUpdateObject) GetBodyType() string {
	return "NewOrUpdateObject"
}

func (b *BodyNewOrUpdateObject) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Object的基本信息更新的事件
type BodyObjectInfoUpdated struct {
	serder.Metadata `union:"ObjectInfoUpdated"`
	Type            string          `json:"type"`
	Object          clitypes.Object `json:"object"`
}

func (b *BodyObjectInfoUpdated) GetBodyType() string {
	return "ObjectInfoUpdated"
}

func (b *BodyObjectInfoUpdated) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Object删除的事件
type BodyObjectDeleted struct {
	serder.Metadata `union:"ObjectDeleted"`
	Type            string            `json:"type"`
	ObjectID        clitypes.ObjectID `json:"objectID"`
}

func (b *BodyObjectDeleted) GetBodyType() string {
	return "ObjectDeleted"
}

func (b *BodyObjectDeleted) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// 新增Package的事件
type BodyNewPackage struct {
	serder.Metadata `union:"NewPackage"`
	Type            string           `json:"type"`
	Info            clitypes.Package `json:"info"`
}

func (b *BodyNewPackage) GetBodyType() string {
	return "NewPackage"
}

func (b *BodyNewPackage) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Package克隆的事件
type BodyPackageCloned struct {
	serder.Metadata `union:"PackageCloned"`
	Type            string              `json:"type"`
	SourcePackageID clitypes.PackageID  `json:"sourcePackageID"`
	NewPackage      clitypes.Package    `json:"newPackage"`
	SourceObjectIDs []clitypes.ObjectID `json:"sourceObjectIDs"` // 原本的ObjectID
	NewObjectIDs    []clitypes.ObjectID `json:"newObjectIDs"`    // 复制后的新ObjectID，与SourceObjectIDs一一对应
}

func (b *BodyPackageCloned) GetBodyType() string {
	return "PackageCloned"
}

func (b *BodyPackageCloned) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Package删除的事件
type BodyPackageDeleted struct {
	serder.Metadata `union:"PackageDeleted"`
	Type            string             `json:"type"`
	PackageID       clitypes.PackageID `json:"packageID"`
}

func (b *BodyPackageDeleted) GetBodyType() string {
	return "PackageDeleted"
}

func (b *BodyPackageDeleted) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// 新增Bucket的事件
type BodyNewBucket struct {
	serder.Metadata `union:"NewBucket"`
	Type            string          `json:"type"`
	Info            clitypes.Bucket `json:"info"`
}

func (b *BodyNewBucket) GetBodyType() string {
	return "NewBucket"
}

func (b *BodyNewBucket) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}

// Bucket删除的事件
type BodyBucketDeleted struct {
	serder.Metadata `union:"BucketDeleted"`
	Type            string            `json:"type"`
	BucketID        clitypes.BucketID `json:"bucketID"`
}

func (b *BodyBucketDeleted) GetBodyType() string {
	return "BucketDeleted"
}

func (b *BodyBucketDeleted) OnUnionSerializing() {
	b.Type = b.GetBodyType()
}
