// 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["colname"] = m.ColumnNames
	m.Attributes["coldesc"] = 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["colname"])
	m.ColumnDescs = get_column_names(obj["coldesc"])

	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,
		"colname": true,
		"coldesc": 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
	}
}
