package transform

import (
	"bytes"
	"fmt"
	"io"

	"gordenko.dev/dima/qb/bin"
	"gordenko.dev/dima/qb/proto"
)

// CHUNKED RESPONDER

var endMsg = []byte{
	proto.RespEndOfValue, // end of stream
}

type ChunkedResponder struct {
	recordsQty int
	buf        *bytes.Buffer
	dst        io.Writer
}

func NewChunkedResponder(dst io.Writer) *ChunkedResponder {
	s := &ChunkedResponder{
		recordsQty: 0,
		buf:        bytes.NewBuffer(nil),
		dst:        dst,
	}

	s.buf.Write([]byte{
		proto.RespPartOfValue, // message type
		0, 0, 0, 0,            // records qty
	})
	return s
}

func (s *ChunkedResponder) BufferRecord(rec []byte) {
	s.buf.Write(rec)
	s.recordsQty++
}

func (s *ChunkedResponder) AppendRecord(rec []byte) error {
	s.buf.Write(rec)
	s.recordsQty++

	if s.buf.Len() < 1500 {
		return nil
	}

	if err := s.sendBuffered(); err != nil {
		return err
	}

	s.buf.Write([]byte{
		proto.RespPartOfValue, // message type
		0, 0, 0, 0,            // records qty
	})
	s.recordsQty = 0
	return nil
}

func (s *ChunkedResponder) Flush() error {
	if s.recordsQty > 0 {
		if err := s.sendBuffered(); err != nil {
			return err
		}
	}

	if _, err := s.dst.Write(endMsg); err != nil {
		return err
	}
	//fmt.Printf("sent endMsg %d\n", endMsg)
	return nil
}

func (s *ChunkedResponder) sendBuffered() (err error) {
	msg := s.buf.Bytes()
	bin.PutUint32(msg[1:], uint32(s.recordsQty))
	//fmt.Printf("put uint16: %d\n", msg[:3])

	//fmt.Printf("send %d records\n", s.recordsQty)

	//fmt.Printf("send buffered: %d, qty: %d\n", msg, s.recordsQty)

	n, err := s.dst.Write(msg)
	if err != nil {
		return
	}

	if n != len(msg) {
		return fmt.Errorf("incomplete write %d bytes instead of %d", n, len(msg))
	}

	s.buf.Reset()
	return
}

// Для Aggregation пишем функцию определения периода и пуляем фактические периоды
//

// By default net/http.Server uses 4KB buffers, which are flushed to client with chunked responses.
// These buffers may result in visible overhead for responses exceeding a few megabytes.
// So allocate 64Kb buffers.
// bw: bufio.NewWriterSize(w, 64*1024),
