package fileutil

import (
	"bufio"
	"io"
	"os"
	"strconv"
	"sync"
	log "tiloader/pkg/logutil"
	"time"
)

//数据文件一行
type RowData struct {
	Data map[string]ColumnData //key字段名, value字段值
}

//数据文件字段值
type ColumnData struct {
	Data     string
	IsNull   bool
	IsImport bool //是否导入 true:导入,false:不导入
}

type DataFileParser struct {
}

/*
*	根据描述文件，解析数据文件，逐行生成数据放入rowDataCh
 */
func (parser DataFileParser) Parse(descFile DescFile, rowDataCh chan RowData, wg *sync.WaitGroup) {
	log.WriteLog("parse data file begin")
	for i := 0; i < 10; i++ {
		colMap := make(map[string]ColumnData, 100)
		colMap["col1"] = ColumnData{"a" + strconv.Itoa(i), false, true}
		colMap["col2"] = ColumnData{"b" + strconv.Itoa(i), false, true}
		colMap["col3"] = ColumnData{"c" + strconv.Itoa(i), false, true}

		rowData := RowData{colMap}

		time.Sleep(time.Second)
		rowDataCh <- rowData
	}
	close(rowDataCh)
	wg.Done()
	log.WriteLog("parse data file end")
}

/*跳过指定行数，返回偏移位置*/
func SkipLinesFromFile(reader *bufio.Reader, skip int64) (skipoffset int64, err error) {
	var i int64
	for i = 0; i < skip; i++ {
		lineBytes, err := reader.ReadBytes('\n')
		if err != nil {
			if err == io.EOF {
				log.WriteLog("文件读写完毕")
			}
			return skipoffset, err
		}
		skipoffset = skipoffset + int64(len(lineBytes))
	}
	return skipoffset, nil
}

func (parser DataFileParser) ReadRows2(descFile DescFile, skip int64, readChan []chan string, wg *sync.WaitGroup, workerNum int) (err error) {
	var (
		file       *os.File
		skipoffset int64
		reader     *bufio.Reader
	)
	checkFileExists(descFile.DataFileName)
	file, err = os.OpenFile(descFile.DataFileName, os.O_RDONLY, 0666)
	if err != nil {
		log.Error(err.Error())
		return err
	}
	defer func() {
		err = file.Close() //close after checking err
	}()
	// 封装为 bufio
	file.Seek(0, 0)
	reader = bufio.NewReader(file)
	skipoffset, err = SkipLinesFromFile(reader, skip)
	if err != nil {
		return err
	}
	//readChan = make(chan string, 1000)
	wg.Add(1)
	go ReadToChan2(readChan, descFile, skipoffset, wg, workerNum)

	return err
}

/*将文件的数据读取出来放到 chan中*/
func ReadToChan2(readChan []chan string, descFile DescFile, skipoffset int64, wg *sync.WaitGroup, workerNum int) {
	var iRownum int
	// defer close(readChan)
	// var iCount [10]int
	defer func() {
		for i := 0; i < workerNum; i++ {
			close(readChan[i])
		}
	}()
	defer wg.Done()
	file, err := os.OpenFile(descFile.DataFileName, os.O_RDONLY, 0666)
	if err != nil {
		log.Error(err.Error())
		return
	}
	defer func() {
		err = file.Close() //close after checking err
	}()
	file.Seek(skipoffset, 0)
	reader := bufio.NewReader(file)
	iRownum = 0
	// if strings.ToUpper(descFile.Charset) == "GBK" {
	// 	enc := mahonia.NewDecoder("GBK")
	// 	for {
	// 		str, err := reader.ReadString('\n')
	// 		encstr := enc.ConvertString(str)

	// 		if err != nil {
	// 			if err != io.EOF {
	// 				log.Error(err.Error())
	// 			}
	// 			break
	// 		}
	// 		idx := iRownum % workerNum
	// 		readChan[idx] <- encstr
	// 		iRownum++
	// 	}
	// } else { //默认UTF-8编码
	for {
		str, err := reader.ReadString('\n')
		if err != nil {
			if err != io.EOF {
				log.Error(err.Error())
			}
			break
		}
		idx := iRownum % workerNum
		readChan[idx] <- str
		iRownum++
	}
	// }
	log.WriteLog("read data file total lines:" + strconv.Itoa(iRownum))

	return
}

func validUTF8(buf []byte) bool {
	nBytes := 0
	for i := 0; i < len(buf); i++ {
		if nBytes == 0 {
			if (buf[i] & 0x80) != 0 { //与操作之后不为0，说明首位为1
				for (buf[i] & 0x80) != 0 {
					buf[i] <<= 1 //左移一位
					nBytes++     //记录字符共占几个字节
				}

				if nBytes < 2 || nBytes > 6 { //因为UTF8编码单字符最多不超过6个字节
					return false
				}

				nBytes-- //减掉首字节的一个计数
			}
		} else { //处理多字节字符
			if buf[i]&0xc0 != 0x80 { //判断多字节后面的字节是否是10开头
				return false
			}
			nBytes--
		}
	}
	return nBytes == 0
}

func checkFileExists(path string) {
	_, err := os.Stat(path)
	if err != nil {
		log.WriteLog("data file not exist:" + path)
		log.Error("data file not exist:" + path)
		os.Exit(2)
	}
}
