package mempool

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"

	"github.com/gorilla/websocket"
)

var (
	ErrNotWebsocket = errors.New("provided addr was not websocket")
)

type mempool struct {
	addr string
	ws   *websocket.Conn
}

func New(addr string) *mempool {
	return &mempool{
		addr: addr,
	}
}

func (m *mempool) Init() error {
	u, err := url.Parse(m.addr)
	if err != nil {
		return err
	}

	if u.Scheme != "wss" && u.Scheme != "ws" {
		return fmt.Errorf("%w: got %s", ErrNotWebsocket, u.Scheme)
	}

	c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
	if err != nil {
		return err
	}

	m.ws = c
	return nil
}

func (m *mempool) Listen(ctx context.Context, blocks chan Block, errs chan error, done chan struct{}) {
	for {
		select {
		case <-ctx.Done():
			close(blocks)
			close(errs)
			close(done)
			return
		default:
			_, message, err := m.ws.ReadMessage()
			if err != nil {
				errs <- err
				continue
			}

			var b Block
			err = json.Unmarshal(message, &b)
			if err != nil {
				errs <- err
				continue
			}

			blocks <- b
		}
	}
}

func (m *mempool) Shutdown(ctx context.Context) error {
	err := m.ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
	if err != nil {
		return err
	}
	m.ws.Close()
	return nil
}
