package server

import (
	"time"

	"github.com/gorilla/websocket"
	"github.com/mailru/easyjson"
)

type wsConn struct {
	conn *websocket.Conn
	in   chan WSRequest
	out  chan WSResponse
}

func newWSConn(conn *websocket.Conn) *wsConn {
	return &wsConn{
		conn: conn,
		in:   make(chan WSRequest, 32),
		out:  make(chan WSResponse, 32),
	}
}

func (c *wsConn) send() {
	var err error
	ping := time.Tick(20 * time.Second)

	for {
		select {
		case res, ok := <-c.out:
			if !ok {
				return
			}

			err = c.writeJSON(res)

		case <-ping:
			err = c.writeJSON(WSResponse{Type: "ping"})
		}

		if err != nil {
			return
		}
	}
}

func (c *wsConn) recv() {
	var req WSRequest

	for {
		err := c.readJSON(&req)
		if err != nil {
			close(c.in)
			return
		}

		c.in <- req
	}
}

func (c *wsConn) close() {
	close(c.out)
	c.conn.Close()
}

func (c *wsConn) readJSON(v easyjson.Unmarshaler) error {
	_, r, err := c.conn.NextReader()
	if err != nil {
		return err
	}

	return easyjson.UnmarshalFromReader(r, v)
}

func (c *wsConn) writeJSON(v easyjson.Marshaler) error {
	w, err := c.conn.NextWriter(websocket.TextMessage)
	if err != nil {
		return err
	}
	_, err1 := easyjson.MarshalToWriter(v, w)
	err2 := w.Close()
	if err1 != nil {
		return err1
	}
	return err2
}