package xugu

import (
	"database/sql/driver"
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"reflect"
	"time"
)

type xuguRows struct {
	rows_conn *xuguConn

	results  *SelectResult
	colIdx   int
	prepared bool
}

func (row *xuguRows) Next(dest []driver.Value) error {

	if row.results.rowIdx >= len(row.results.Values[0]) {
		//return errors.New("The result set has been released")
		return io.EOF
	}
	//	fmt.Println(" -- int(row.results.Field_Num)", int(row.results.Field_Num))

	for j := 0; j < int(row.results.Field_Num); j++ {

		coluType := row.results.Fields[j].FieldType
		//fmt.Println("  --coluType: ", coluType, row.results.Fields[j].typeDatabaseName())
		if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
			dest[j] = nil
		} else {
			switch coluType {

			case fieldType_BINARY,
				fieldType_CLOB,
				fieldType_BLOB:
				fmt.Println(row.results.Values[j][row.results.rowIdx].Col_Data)
				dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data

			case fieldType_INTERVAL_Y, fieldType_INTERVAL_M, fieldType_INTERVAL_D,
				fieldType_INTERVAL_H, fieldType_INTERVAL_S,
				fieldType_INTERVAL_MI:
				dest[j] = binary.BigEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data)

			case fieldType_TIME,
				fieldType_TIME_TZ:
				timeTmp := int32(binary.BigEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data))
				//tv, _ := time.Parse("2006-01-02 15:04:05", string(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data)))
				tv := time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC).Add((time.Millisecond * time.Duration(timeTmp)))
				utcTime := tv.UTC()
				dest[j] = utcTime
			case fieldType_DATE:

				timeTmp := int32(binary.BigEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data))
				//tv, _ := time.Parse("2006-01-02 15:04:05", string(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data)))
				tv := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC).Add((time.Hour * 24 * time.Duration(timeTmp)))
				utcTime := tv.UTC()
				dest[j] = utcTime
				// fmt.Println(string(row.results.Values[j][row.results.rowIdx].Col_Data))
				// tv, _ := time.Parse("15:04:05", string(row.results.Values[j][row.results.rowIdx].Col_Data))
				// dest[j] = tv

			case fieldType_DATETIME,
				fieldType_DATETIME_TZ:

				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					//timeTmp := binary.LittleEndian.Uint64(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data)
					timeTmp := binary.BigEndian.Uint64(row.results.Values[j][row.results.rowIdx].Col_Data)
					//tv, _ := time.Parse("2006-01-02 15:04:05", string(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data)))
					tv := time.Unix(0, int64(timeTmp)*1000000)
					utcTime := tv.UTC()
					dest[j] = utcTime
				}

			case fieldType_R4:
				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					dest[j] = math.Float32frombits(binary.BigEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data))
				}

			case fieldType_R8:
				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					dest[j] = math.Float64frombits(binary.BigEndian.Uint64(row.results.Values[j][row.results.rowIdx].Col_Data))
				}
			case fieldType_NUM:
				dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data
			case fieldType_I1:
				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					dest[j] = int8(row.results.Values[j][row.results.rowIdx].Col_Data[0])
				}
			case fieldType_I2:
				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					dest[j] = int16(binary.BigEndian.Uint16(row.results.Values[j][row.results.rowIdx].Col_Data))
				}
			case fieldType_I4:
				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					dest[j] = int32(binary.BigEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data))
				}
			case fieldType_I8:
				if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
					dest[j] = nil
				} else {
					dest[j] = int64(binary.BigEndian.Uint64(row.results.Values[j][row.results.rowIdx].Col_Data))
					//dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data
				}
			case fieldType_CHAR, fieldType_NCHAR:
				if row.results.Values[j][row.results.rowIdx].Col_Data == nil {
					dest[j] = string("")
				} else if row.results.Values[j][row.results.rowIdx].Col_Data[0] == 0x00 {
					dest[j] = string("")
				} else {
					dest[j] = string(row.results.Values[j][row.results.rowIdx].Col_Data)
				}
			default:

				//填入一行的数据
				//TODO这里长度改为一行长度
				dest[j] = make([]byte, len(row.results.Values))
				// Values[字段][0]
				dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data

			}
		}
	}
	row.results.rowIdx++

	return nil
}

// Columns返回列的名字集,它的个数是从slice的长度中推断出来的。
// 如果不知道特定的列名,应该为该条目返回一个空的字符串
func (row *xuguRows) Columns() []string {

	var columns []string

	for _, v := range row.results.Fields {
		columns = append(columns, v.FieldName)
	}

	return columns
}

func (row *xuguRows) ColumnTypeScanType(index int) reflect.Type {
	fmt.Println(">>>>>ColumnTypeScanType ")

	return row.results.Fields[index].scanType()
}

func (self *xuguRows) Close() error {
	return nil
}