package seller

import (
	"Wine-Server/utils"
	"Wine-Server/utils/tables"
	"database/sql"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

func sellerConnected(seq string, conn *websocket.Conn) *tables.DeviceTable {
	device := tables.DeviceTable{Id: seq}
	err := device.Get()
	if err == sql.ErrNoRows { // insert new device
		err = device.Insert()
		if err != nil {
			utils.Logger.Println("new device join failed:", err)
			_ = conn.WriteJSON(utils.WsError("New device join failed"))
			return nil
		}
		_ = device.Get()
	} else { // update last time
		device.Last = utils.TimeNow()
		err = device.Update(utils.JsonType{"last": device.Last})
		if err != nil {
			utils.Logger.Println("update last active time failed:", err)
			_ = conn.WriteJSON(utils.WsError("Update last active time failed"))
			return nil
		}
	}

	exist := false
	utils.SellerLock.Lock()
	if pointer, sin := utils.SellerDevices[seq]; sin {
		pointer.Online = true
		exist = true
		pointer.Conn = conn
	} else {
		utils.SellerDevices[seq] = &utils.SellerDevice{Online: true, Conn: conn}
	}
	utils.SellerLock.Unlock()
	if exist {
		for _, debugger := range utils.DebugWss {
			_ = debugger.WriteJSON(utils.WsEvent("deviceStatusChange", utils.JsonType{"seq": seq, "online": true}))
		}
	} else {
		for _, debugger := range utils.DebugWss {
			_ = debugger.WriteJSON(utils.WsEvent("newDevice", utils.JsonType{
				"seq": seq, "online": true, "location": device.Addr,
				"ppv1": device.Wines[0].Ppv, "ppv2": device.Wines[1].Ppv,
				"ppv3": device.Wines[2].Ppv, "ppv4": device.Wines[3].Ppv,
			}))
		}
	}
	utils.Logger.Printf("device[%s] connected\n", seq)
	return &device
}

func sellerDisconnect(seq string) {
	utils.SellerLock.Lock()
	utils.SellerDevices[seq].Online = false
	utils.SellerLock.Unlock()
	for _, debugger := range utils.DebugWss {
		_ = debugger.WriteJSON(utils.WsEvent("deviceStatusChange", utils.JsonType{"seq": seq, "online": false}))
	}
	utils.Logger.Printf("device[%s] disconnected\n", seq)
}

func SocketHandler(ctx *gin.Context) {
	conn, err := utils.UpgradeHttp2Ws.Upgrade(ctx.Writer, ctx.Request, nil)
	if err != nil {
		utils.Logger.Println("can't establish seller socket connect")
		ctx.JSON(utils.HttpError, utils.Fail("can't establish socket connect"))
		return
	}
	seq := ctx.Param("seq")
	if seq == "" {
		_ = conn.WriteJSON(utils.WsError("device seq is required"))
		return
	}

	device := sellerConnected(seq, conn)
	if device == nil {
		sellerDisconnect(seq)
		return
	}
	infoOfDevice(device, conn)
	for {
		var msg utils.WsMsg
		err = conn.ReadJSON(&msg)
		if err != nil {
			sellerDisconnect(seq)
			return
		}
		switch msg.Event {
		case "pin":
			keepAlive(conn, msg.Data)
			break
		case "getQrcode":
			getQrcode(device, conn, msg.Data)
			break
		case "checkAuthCode":
			checkAuthCode(device.Id, conn, msg.Data)
			break
		case "openResult":
			openResult(conn, msg.Data)
			break
		case "workFinished":
			workFinished(conn, msg.Data)
			break
		default:
			_ = conn.WriteJSON(utils.WsError("unrecognized event"))
			break
		}
	}
}
