//go:build windows

package yu_file

import (
	yu_bytes "gogs.qqck.cn/s/tools/bytes"
	yu_sys "gogs.qqck.cn/s/tools/sys"
)

// GetEx
//
//	@Description: 独占方式(多线程安全)读文件
//	@param name 文件路径
//	@param start 读入起始位置
//	@param size 读入字节数
func GetEx(name string, start int64, size int) (result []byte) {
	j_fd := Openfile(name, yu_sys.GENERIC_READ, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_EXISTING, 0)
	if j_fd == 0 {
		return
	}
	defer yu_sys.CloseHandle.Call(j_fd)
	if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) {
		return
	}
	j_size, j_ok := getFileSizeEx(j_fd)
	if !j_ok {
		return
	}
	if j_size == 0 || start+int64(size) > j_size {
		return
	}
	return readFileSize(j_fd, size)
}

// SetEx
//
//	@Description: 独占方式(多线程安全)写文件
//	@param name 文件路径
//	@param start 写出起始位置
//	@param bufs 写出内容...
func SetEx(name string, start int64, bufs ...[]byte) bool {
	j_fd := Openfile(name, yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH)
	if j_fd == 0 {
		return false
	}
	defer yu_sys.CloseHandle.Call(j_fd)
	if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) {
		return false
	}
	for j_i := 0; j_i < len(bufs); j_i++ {
		if !writeFile(j_fd, bufs[j_i]) {
			return false
		}
	}
	return true
}

// Add
//
//	@Description: 独占方式(多线程安全)读写文件计数已实现持久化存储计数
//	@param name 文件路径
//	@param start 读取位置偏移(以该位置往后8个字节为存储数据)
//	@param on 计算回调，传 nil 则只读取
//	@return int64 最终存储结果
func Add(name string, start int64, on func(old int64) int64) int64 {
	j_fd := Openfile(name, yu_sys.GENERIC_READ|yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH)
	if j_fd == 0 {
		return 0
	}
	defer yu_sys.CloseHandle.Call(j_fd)
	if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) {
		return 0
	}
	j_buf := make([]byte, 8)
	readFileBuf(j_fd, j_buf)
	j_result := int64(j_buf[0]) | int64(j_buf[1])<<8 |
		int64(j_buf[2])<<16 | int64(j_buf[3])<<24 |
		int64(j_buf[4])<<32 | int64(j_buf[5])<<40 |
		int64(j_buf[6])<<48 | int64(j_buf[7])<<56
	if on == nil {
		return j_result
	}
	j_result = on(j_result)
	j_buf[0] = byte(j_result)
	j_buf[1] = byte(j_result >> 8)
	j_buf[2] = byte(j_result >> 16)
	j_buf[3] = byte(j_result >> 24)
	j_buf[4] = byte(j_result >> 32)
	j_buf[5] = byte(j_result >> 40)
	j_buf[6] = byte(j_result >> 48)
	j_buf[7] = byte(j_result >> 56)
	if yu_sys.SetFilePointerEx.CallBool(j_fd, 0, 0, yu_sys.FILE_BEGIN) {
		writeFile(j_fd, j_buf)
	}
	return j_result
}

const (
	lines_size = 1024 * 1024 * 32
)

// ForInfo
// @Description: For 数据结构体
type ForInfo struct {

	// Start 当前数据的读入起始位置
	Start int64

	// Size 当前数据的总大小，如果为 -1 则自动调用api读取实际文件大小
	Size int64

	// ForSize 循环的数据总大小
	ForSize int64

	// ForGetN 已循环次数
	ForGetN int64

	// ForGetMax 最多读取循环数据的次数，超过该次数后未循环的读取完毕将不再读取循环的数据，-1为不限制
	ForGetMax int64
}

func NewForInfo() ForInfo {
	return ForInfo{
		Start:     0,
		Size:      -1,
		ForSize:   0,
		ForGetN:   0,
		ForGetMax: 0,
	}
}

// En
//
//	@Description: 编码数据
func (t *ForInfo) En() [40]byte {
	j_buf := [40]byte{}
	j_buf[0] = byte(t.Start)
	j_buf[1] = byte(t.Start >> 8)
	j_buf[2] = byte(t.Start >> 16)
	j_buf[3] = byte(t.Start >> 24)
	j_buf[4] = byte(t.Start >> 32)
	j_buf[5] = byte(t.Start >> 40)
	j_buf[6] = byte(t.Start >> 48)
	j_buf[7] = byte(t.Start >> 56)

	j_buf[8] = byte(t.Size)
	j_buf[9] = byte(t.Size >> 8)
	j_buf[10] = byte(t.Size >> 16)
	j_buf[11] = byte(t.Size >> 24)
	j_buf[12] = byte(t.Size >> 32)
	j_buf[13] = byte(t.Size >> 40)
	j_buf[14] = byte(t.Size >> 48)
	j_buf[15] = byte(t.Size >> 56)

	j_buf[16] = byte(t.ForSize)
	j_buf[17] = byte(t.ForSize >> 8)
	j_buf[18] = byte(t.ForSize >> 16)
	j_buf[19] = byte(t.ForSize >> 24)
	j_buf[20] = byte(t.ForSize >> 32)
	j_buf[21] = byte(t.ForSize >> 40)
	j_buf[22] = byte(t.ForSize >> 48)
	j_buf[23] = byte(t.ForSize >> 56)

	j_buf[24] = byte(t.ForGetN)
	j_buf[25] = byte(t.ForGetN >> 8)
	j_buf[26] = byte(t.ForGetN >> 16)
	j_buf[27] = byte(t.ForGetN >> 24)
	j_buf[28] = byte(t.ForGetN >> 32)
	j_buf[29] = byte(t.ForGetN >> 40)
	j_buf[30] = byte(t.ForGetN >> 48)
	j_buf[31] = byte(t.ForGetN >> 56)

	j_buf[32] = byte(t.ForGetMax)
	j_buf[33] = byte(t.ForGetMax >> 8)
	j_buf[34] = byte(t.ForGetMax >> 16)
	j_buf[35] = byte(t.ForGetMax >> 24)
	j_buf[36] = byte(t.ForGetMax >> 32)
	j_buf[37] = byte(t.ForGetMax >> 40)
	j_buf[38] = byte(t.ForGetMax >> 48)
	j_buf[39] = byte(t.ForGetMax >> 56)

	return j_buf
}

// De
//
//	@Description: 解码数据
func (t *ForInfo) De(data [40]byte) {
	t.Start = int64(data[0]) | int64(data[1])<<8 | int64(data[2])<<16 | int64(data[3])<<24 |
		int64(data[4])<<32 | int64(data[5])<<40 | int64(data[6])<<48 | int64(data[7])<<56

	t.Size = int64(data[8]) | int64(data[9])<<8 | int64(data[10])<<16 | int64(data[11])<<24 |
		int64(data[12])<<32 | int64(data[13])<<40 | int64(data[14])<<48 | int64(data[15])<<56

	t.ForSize = int64(data[16]) | int64(data[17])<<8 | int64(data[18])<<16 | int64(data[19])<<24 |
		int64(data[20])<<32 | int64(data[21])<<40 | int64(data[22])<<48 | int64(data[23])<<56

	t.ForGetN = int64(data[24]) | int64(data[25])<<8 | int64(data[26])<<16 | int64(data[27])<<24 |
		int64(data[28])<<32 | int64(data[29])<<40 | int64(data[30])<<48 | int64(data[31])<<56

	t.ForGetMax = int64(data[32]) | int64(data[33])<<8 | int64(data[34])<<16 | int64(data[35])<<24 |
		int64(data[36])<<32 | int64(data[37])<<40 | int64(data[38])<<48 | int64(data[39])<<56
}

// ForGet
//
//	@Description: 独占方式(多线程安全)读取文件内容
//	@param name 文件路径
//	@param eof 截止标志
//	@param min 最小读取字节数
//	@param max 最大读取字节数
//	@param seek_get ForInfo 信息获取函数
//	@param seek_set ForInfo 信息更新保存函数
//	@return []byte 读取内容
func ForGet(name string, eof []byte, min, max int64, seek_get func() ForInfo, seek_set func(ForInfo)) []byte {
	if seek_get == nil {
		return nil
	}
	j_fd := Openfile(name, yu_sys.GENERIC_READ, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_EXISTING, 0)
	if j_fd == 0 {
		return nil
	}
	defer yu_sys.CloseHandle.Call(j_fd)
	j_info := seek_get()
	j_eof_len := int64(len(eof))
	if j_info.Size < 0 && !yu_sys.GetFileSizeEx.CallBool(j_fd, &j_info.Size) {
		return nil
	}
	if max < min {
		max += min
	}
_get:
	j_get_size := j_info.Size - j_info.Start
	if j_get_size > 0 {
		// ------------------------------------------------------------------------判断剩余字节数如果小于等于 max 或 eof 直接读入全部
		if j_get_size <= max || j_get_size <= j_eof_len {
			if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start, 0, yu_sys.FILE_BEGIN) {
				return nil
			}
			j_result := make([]byte, j_get_size)
			j_get_size = readFileBuf(j_fd, j_result)
			if seek_set != nil {
				j_info.Start += j_get_size
				seek_set(j_info)
			}
			return j_result[:j_get_size]
		}
		// ------------------------------------------------------------------------检索 eof 标志
		j_result := make([]byte, j_eof_len)
		for {
			if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start+min, 0, yu_sys.FILE_BEGIN) {
				return nil
			}
			j_get_size = readFileBuf(j_fd, j_result)
			if j_get_size == 0 || j_get_size < j_eof_len {
				return nil
			}
			if yu_bytes.Equals(j_result, eof) {
				break
			}
			if min++; min > max {
				return nil
			} // 到当前数据的上限了，读入失败
		}
		if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start, 0, yu_sys.FILE_BEGIN) {
			return nil
		}
		j_result = make([]byte, min+j_eof_len)
		j_get_size = readFileBuf(j_fd, j_result)
		if seek_set != nil {
			j_info.Start += j_get_size
			seek_set(j_info)
		}
		return j_result[:j_get_size-j_eof_len] // 删除尾部 eof 标志
	}
	// ------------------------------------------------------------------------判断是否从循环里读取数据
	if j_info.ForSize == 0 {
		return nil
	}
	if j_info.ForGetMax > -1 && j_info.ForGetN >= j_info.ForGetMax {
		return nil
	}
	j_info.Start, j_info.Size, j_info.ForSize = 0, j_info.ForSize, 0 // 重置当前数据结构
	j_info.ForGetN++
	goto _get
}

// ForPut
//
//	@Description: 独占方式(多线程安全)写出文件内容
//	@param name 文件路径
//	@param seek_get ForInfo 信息获取函数
//	@param seek_set ForInfo 信息更新保存函数
//	@param bufs 欲写出的书...
//	@return bool 是否操作成功
func ForPut(name string, seek_get func() ForInfo, seek_set func(ForInfo), bufs ...[]byte) bool {
	if seek_get == nil {
		return false
	}
	j_fd := Openfile(name, yu_sys.GENERIC_READ|yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH)
	if j_fd == 0 {
		return false
	}
	defer yu_sys.CloseHandle.Call(j_fd)
	j_info := seek_get()
	if j_info.Size < 0 && !yu_sys.GetFileSizeEx.CallBool(j_fd, &j_info.Size) {
		return false
	}
	for j_i := 0; j_i < len(bufs); j_i++ {
		// 判断是往循环里写数据还是在文件末尾追加数据
		j_buf_len := int64(len(bufs[j_i]))
		if j_info.Start-j_info.ForSize > j_buf_len {
			// 往循环里写数据
			if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.ForSize, 0, yu_sys.FILE_BEGIN) {
				return false
			}
			if !writeFile(j_fd, bufs[j_i]) {
				return false
			}
			j_info.ForSize += j_buf_len
		} else {
			// 在文件末尾追加数据
			if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Size, 0, yu_sys.FILE_BEGIN) {
				return false
			}
			if !writeFile(j_fd, bufs[j_i]) {
				return false
			}
			j_info.Size += j_buf_len
		}
		if seek_set != nil {
			seek_set(j_info)
		}
	}
	return true
}
