// message.go
package swservice

import (
	"encoding/json"
	"errors"
	"fmt"
	//	"reflect"
	"strconv"
)

type MessageWriter struct {
	FuncNo      int `json: "funcno"`
	Attributes  map[string]interface{}
	ColumnNames []string
	ColumnDescs []string
	RowData     []map[string]interface{}
	Row         map[string]interface{}
}

func NewMessageWriter(funcno int) *MessageWriter {
	return &MessageWriter{
		FuncNo:      funcno,
		Attributes:  make(map[string]interface{}),
		ColumnNames: make([]string, 0),
		ColumnDescs: make([]string, 0),
		RowData:     make([]map[string]interface{}, 0)}
}
func (m *MessageWriter) SetAttr(name string, value interface{}) {
	m.Attributes[name] = value
}
func (m *MessageWriter) AddCol(name string, value interface{}) {
	if m.Row == nil {
		m.Row = make(map[string]interface{})
	}
	m.Row[name] = value
}

func is_contains(k string, slice []string) bool {
	for _, v := range slice {
		if k == v {
			return true
		}
	}
	return false
}

func (m *MessageWriter) AddRow() {
	if m.Row == nil {
		return
	}
	//	data := make([]interface{}, 0)
	//	if len(m.ColumnNames) == 0 {
	//		for k, v := range m.Row {
	//			m.ColumnNames = append(m.ColumnNames, k)
	//			data = append(data, v)
	//		}
	//	} else {
	//		for _, n := range m.ColumnNames {
	//			if v, ok := m.Row[n]; !ok {
	//				data = append(data, nil)
	//			} else {
	//				data = append(data, v)
	//			}
	//		}
	//		for k, v := range m.Row {
	//			if !is_contains(k, m.ColumnNames) {
	//				m.ColumnNames = append(m.ColumnNames, k)
	//				data = append(data, v)
	//			}
	//		}
	//	}
	//	m.RowData = append(m.RowData, data)
	m.RowData = append(m.RowData, m.Row)
	m.Row = nil
}

func (m *MessageWriter) serialize_rowdata() {
	m.ColumnNames = make([]string, 0)
	for _, row := range m.RowData {
		for k, _ := range row {
			if !is_contains(k, m.ColumnNames) {
				m.ColumnNames = append(m.ColumnNames, k)
			}
		}
	}
	rows := make([][]interface{}, 0)
	for _, row := range m.RowData {
		data := make([]interface{}, 0)
		for _, k := range m.ColumnNames {
			if v, ok := row[k]; !ok {
				data = append(data, nil)
			} else {
				data = append(data, v)
			}
		}
		rows = append(rows, data)
	}
	m.Attributes["rowdata"] = rows
	m.Attributes["rowcnt"] = len(rows)
}

func (m *MessageWriter) Serialize() string {
	m.Attributes["funcno"] = m.FuncNo
	m.serialize_rowdata()
	m.Attributes["colnames"] = m.ColumnNames
	m.Attributes["coldescs"] = m.ColumnNames
	m.Attributes["colcnt"] = len(m.ColumnNames)
	r, _ := json.Marshal(m.Attributes)
	return string(r)
}

//////////////////////////////////////////////////////////////////////
type MessageReader struct {
	FuncNo      int
	RetCode     int
	RetMsg      string
	DBMsg       string
	ErrName     string
	ColumnNames []string
	ColumnDescs []string
	Attributes  map[string]interface{}
	RowData     []map[string]interface{}
	RowIndex    int
}

func get_value_as_int(value interface{}) int {
	//	vtype := reflect.TypeOf(value)
	switch value.(type) {
	case int:
		return value.(int)
	case float64:
		return int(value.(float64))
	case string:
		i, _ := strconv.Atoi(value.(string))
		return i
	default:
		panic("Error")
	}
}

func get_column_names(data interface{}) (result []string) {
	if data == nil {
		return nil
	}
	names := data.([]interface{})
	result = make([]string, 0)
	for _, v := range names {
		result = append(result, v.(string))
	}
	return
}

func convert_to_int(value interface{}) int {
	if value == nil {
		return 0
	}
	switch value.(type) {
	case int:
		return value.(int)
	case float64:
		return int(value.(float64))
	case string:
		i, _ := strconv.Atoi(value.(string))
		return i
	default:
		return 0
	}
}

func convert_to_string(value interface{}) string {
	if value == nil {
		return ""
	}
	return fmt.Sprintf("%v", value)
}

func NewMessageReader(data []byte) *MessageReader {
	var s interface{}
	err := json.Unmarshal(data, &s)
	if err != nil {
		return nil
	}
	obj := s.(map[string]interface{})

	m := &MessageReader{Attributes: make(map[string]interface{}),
		RowData: make([]map[string]interface{}, 0)}
	m.FuncNo = convert_to_int(obj["funcno"])
	m.RetCode = convert_to_int(obj["retcode"])
	m.RetMsg = convert_to_string(obj["retmsg"])
	m.DBMsg = convert_to_string(obj["dbmsg"])
	m.ErrName = convert_to_string(obj["errname"])

	m.ColumnNames = get_column_names(obj["colnames"])
	m.ColumnDescs = get_column_names(obj["coldescs"])

	if rowdata, err := obj["rowdata"]; err {
		if rowdata != nil {
			for _, raw := range rowdata.([]interface{}) {
				row := raw.([]interface{})
				data := make(map[string]interface{})
				for idx, v := range row {
					data[m.ColumnNames[idx]] = v
				}
				m.RowData = append(m.RowData, data)
			}
		}
	}
	reverseKey := map[string]bool{
		"funcno":   true,
		"colnames": true,
		"coldescs": true,
		"rowcnt":   true,
		"colcnt":   true,
		"rowdata":  true,
		"retcode":  true,
		"retmsg":   true,
		"dbmsg":    true,
		"errname":  true}

	for k, v := range obj {
		if _, ok := reverseKey[k]; ok {
			continue
		}
		m.Attributes[k] = v
	}
	return m
}

func (m *MessageReader) RowCount() int {
	return len(m.RowData)
}

func (m *MessageReader) HasMore() bool {
	return m.RowIndex < m.RowCount()
}

func (m *MessageReader) NextRow() error {
	m.RowIndex++
	if m.RowIndex > m.RowCount() {
		return errors.New("Eof of row")
	}
	return nil
}

func (m *MessageReader) GetCol(name string) interface{} {
	idx := m.RowIndex - 1
	if v, ok := m.RowData[idx][name]; !ok {
		return nil
	} else {
		return v
	}
}

func (m *MessageReader) GetColAsInt(name string) int {
	v := m.GetCol(name)
	switch v.(type) {
	case float32:
		return int(v.(float32))
	case float64:
		return int(v.(float64))
	case int:
		return v.(int)
	case string:
		i, _ := strconv.Atoi(v.(string))
		return i
	default:
		return 0
	}
}

func (m *MessageReader) GetColAsString(name string) string {
	v := m.GetCol(name)
	return fmt.Sprintf("%v", v)
}

func (m *MessageReader) GetColAsDouble(name string) float64 {
	v := m.GetCol(name)
	switch v.(type) {
	case float32:
		return float64(v.(float32))
	case float64:
		return v.(float64)
	case int:
		return float64(v.(int))
	case string:
		i, _ := strconv.ParseFloat(v.(string), 64)
		return i
	default:
		return 0
	}
}

func (m *MessageReader) GetAttr(name string) interface{} {
	if v, ok := m.Attributes[name]; !ok {
		return nil
	} else {
		return v
	}
}
