package impt

import (
	"dbweb/core"
	"encoding/csv"
	"errors"
	"fmt"
	"io"
	"os"

	"strings"

	"github.com/spkg/bom"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

type charset int

const (
	charsetUTF8 charset = iota
	charsetGBK
)

func (c charset) MarshalJSON() ([]byte, error) {
	switch c {
	case charsetUTF8:
		return []byte(`"UTF8"`), nil
	case charsetGBK:
		return []byte(`"GBK"`), nil
	default:
		return nil, errors.New("not impl")
	}
}
func (c *charset) UnmarshalJSON(val []byte) error {
	switch string(val) {
	case `"UTF8"`:
		*c = charsetUTF8
	case `"GBK"`:
		*c = charsetGBK
	default:
		return errors.New("invalid type " + string(val))
	}
	return nil
}

type format int

const (
	formatCSV format = iota
	formatTAB
	formatCustom
)

func (f format) MarshalJSON() ([]byte, error) {
	switch f {
	case formatCSV:
		return []byte(`"CSV"`), nil
	case formatTAB:
		return []byte(`"TAB"`), nil
	case formatCustom:
		return []byte(`"CUSTOM"`), nil
	default:
		return nil, errors.New("not impl")
	}
}
func (f *format) UnmarshalJSON(val []byte) error {
	switch string(val) {
	case `"CSV"`:
		*f = formatCSV
	case `"TAB"`:
		*f = formatTAB
	case `"CUSTOM"`:
		*f = formatCustom
	default:
		return errors.New("invalid type " + string(val))
	}
	return nil
}

//file 表示一个导入的文件，自动读取第一行
type file struct {
	file     *os.File
	r        *csv.Reader
	firstRow []string
	Title    []string
	Current  int //当前待读取的行号，从0开始
}

func openFile(fileName string, fileCharset charset, fileFormat format,
	customSplit rune, firstHead bool) (*file, error) {
	aFile, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	rev := &file{
		file: aFile,
	}
	//需要去掉bom，参见 https://github.com/golang/go/issues/9588
	f := bom.NewReader(aFile)
	var r io.Reader
	switch fileCharset {
	case charsetUTF8:
		r = f
	case charsetGBK:
		r = transform.NewReader(f, simplifiedchinese.GBK.NewDecoder())
	default:
		core.LOG.Panic("not impl")
	}
	rev.r = csv.NewReader(r)
	switch fileFormat {
	case formatCSV:
	case formatTAB:
		rev.r.Comma = '\t'
	case formatCustom:
		rev.r.Comma = customSplit
	default:
		core.LOG.Panic("not impl")
	}
	//读取第一行
	row, err := rev.r.Read()
	if err != nil {
		return nil, err
	}
	//去除空白
	trimStrings(row)
	if firstHead {
		rev.Title = row
	} else {
		rev.Title = []string{}
		for i := range row {
			rev.Title = append(rev.Title, fmt.Sprintf("col%d", i))
		}
		//保存第一行待读取
		rev.firstRow = row
	}
	//限定每行必须要和第一行列数一致
	rev.r.FieldsPerRecord = len(row)
	return rev, nil
}
func trimStrings(list []string) {
	for i, v := range list {
		list[i] = strings.TrimSpace(v)
	}
}
func (f *file) close() error {
	return f.file.Close()
}
func (f *file) Read() ([]string, error) {
	defer func() {
		f.Current++
	}()
	if f.Current == 0 && f.firstRow != nil {
		return f.firstRow, nil
	}
	r, err := f.r.Read()
	trimStrings(r)
	return r, err
}
