package utils

import (
	"strconv"
	"time"
)

const (
	PhysicalShiftBits = 18
	TSOFactor         = 1000
)

func ExtractPhysical(ts uint64) int64 {
	return int64(ts >> PhysicalShiftBits)
}

// GetTimeFromTS extracts time.Time from a timestamp.
func GetTimeFromTS(ts uint64) time.Time {
	ms := ExtractPhysical(ts)
	return time.Unix(
		ms/int64(time.Second/time.Millisecond),
		(ms%int64(time.Second/time.Millisecond))*int64(time.Millisecond/time.Nanosecond),
	).UTC()
}

func GoTimeToTSO(t time.Time) uint64 {
	ts := (t.UnixNano() / int64(time.Millisecond)) << PhysicalShiftBits
	return uint64(ts)
}

// timestamp to tso
func TransToTSO(ts int64) uint64 {
	return uint64((ts << PhysicalShiftBits) * TSOFactor)
}

func TransToTSOStr(ts int64) string {
	tso := TransToTSO(ts)
	return strconv.FormatUint(tso, 10)
}

// tso to timestamp
func TransToTS(tso uint64) int64 {
	return int64((tso / TSOFactor) >> PhysicalShiftBits)
}
