// 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
	}
}
