/*
Copyright 2016 The Transicator Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pgclient

import (
	"errors"
	"fmt"

	log "github.com/Sirupsen/logrus"
)

/*
A ColumnInfo describes a single row in a query result.
*/
type ColumnInfo struct {
	// Name of the column
	Name string
	// Postgres type OID
	Type PgType
	// Was the column represented in binary form in the result row?
	Binary bool
}

/*
SimpleQuery executes a query as a string, and returns a list of rows.
It does not do any kind of preparation. The first parameter returned is an
array of descriptors for each row. The second is an array of rows.
*/
func (c *PgConnection) SimpleQuery(query string) ([]ColumnInfo, [][]string, error) {
	cols, rawRows, _, err := c.exec(query)
	var rows [][]string
	if err == nil {
		// Convert rows into an array of strings
		for _, rawRow := range rawRows {
			var cols []string
			for _, rawCol := range rawRow {
				cols = append(cols, string(rawCol))
			}
			rows = append(rows, cols)
		}
	}
	return cols, rows, err
}

/*
SimpleExec executes a query as a string, and returns a row count.
It does not do any kind of preparation. The first parameter returned is an
array of descriptors for each row. The second is an array of rows.
*/
func (c *PgConnection) SimpleExec(query string) (int64, error) {
	_, _, rowCount, err := c.exec(query)
	return rowCount, err
}

func (c *PgConnection) exec(query string) ([]ColumnInfo, [][][]byte, int64, error) {
	log.Debugf("Query: %s", query)
	qm := NewOutputMessage(Query)
	qm.WriteString(query)
	err := c.WriteMessage(qm)
	if err != nil {
		return nil, nil, 0, err
	}

	var rowDesc []ColumnInfo
	var rows [][][]byte
	var rowCount int64
	var cmdErr error

	// Loop until we get a ReadyForQuery message, or until we get an error
	// reading messages at all.
	for {
		im, err := c.readStandardMessage()
		if err != nil {
			return nil, nil, 0, err
		}

		switch im.Type() {
		case CommandComplete:
			// Command complete. Could return what we did.
			rowCount, err = ParseCommandComplete(im)
		case CopyInResponse, CopyOutResponse:
			// Copy in/out response -- not yet supported
			cmdErr = errors.New("COPY operations not supported by this client")
		case RowDescription:
			rowDesc, err = ParseRowDescription(im)
			if err != nil {
				cmdErr = err
			}
		case DataRow:
			row, err := ParseDataRow(im)
			if err != nil {
				cmdErr = err
			} else {
				rows = append(rows, row)
			}
		case EmptyQueryResponse:
			// Empty query response. Nothing to do really.
		case ReadyForQuery:
			return rowDesc, rows, rowCount, cmdErr
		case ErrorResponse:
			// Need to record error and keep reading until we get ReadyForQuery
			cmdErr = ParseError(im)
		default:
			cmdErr = fmt.Errorf("Invalid server response %s", im.Type())
		}
	}
}
