package sm

import (
	"encoding/binary"
)

// GM/T 0018中，bits等uint转为字节串时，没有规定大小端序列。这里可以设置按哪种端序进行处理。
// 更新：从字符串转为struct时可以忽略端序，不管大小端，代码中分别进行如下判断。
// 比如[]byte{00,01,00,00}. 小端序为0x00000100 = 256，大端序为0x00010000.
// 可以根据上下文判断是否超过最大值而采用某种端序。

type endian struct {
	isBigEndian bool
}

func (e *endian) PutUint32(b []byte, v uint32) {
	if e.isBigEndian {
		binary.BigEndian.PutUint32(b, v)
	} else {
		binary.LittleEndian.PutUint32(b, v)
	}
}

func (e *endian) Uint32(b []byte) uint32 {
	if e.isBigEndian {
		return binary.BigEndian.Uint32(b)
	}
	return binary.LittleEndian.Uint32(b)

}

var (
	// Endian marshal时int类型的存储端序 - 默认为大端序
	Endian = endian{true}
)

var callBackSetToBigEndian []func()
var callBackSetToLittleEndian []func()
var callBackSetToDefaultEndian []func()

func RegisterCallBack(setToBigEndian, setToLittleEndian, setToDefaultEndian func()) {
	callBackSetToBigEndian = append(callBackSetToBigEndian, setToBigEndian)
	callBackSetToLittleEndian = append(callBackSetToLittleEndian, setToLittleEndian)
	callBackSetToDefaultEndian = append(callBackSetToDefaultEndian, setToDefaultEndian)
}

// SetToBigEndian 将端序设置为大端序
func SetToBigEndian() {
	Endian.isBigEndian = true
	for _, f := range callBackSetToBigEndian {
		f()
	}
}

// SetToLittleEndian 设置为小端序
func SetToLittleEndian() {
	Endian.isBigEndian = false
	for _, f := range callBackSetToLittleEndian {
		f()
	}
}

// SetToDefaultEndian 恢复默认端序-大端
func SetToDefaultEndian() {
	Endian.isBigEndian = true
	for _, f := range callBackSetToDefaultEndian {
		f()
	}
}
