package client

import (
	"encoding/base64"
	"encoding/json"
	"log"
	"time"

	"git.pyer.club/kingecg/goemitter"
	"git.pyer.club/kingecg/gotunnelserver/server"
	"git.pyer.club/kingecg/gotunnelserver/util"
	ws "github.com/gorilla/websocket"
)

type ClientConfig struct {
	Username string
	Salt     string
	Address  string
}

type CommandClient struct {
	*ws.Conn
	*goemitter.EventEmitter
	*ClientConfig
	path      string
	SessionId string
}

func (c *CommandClient) Close() {
	if c.Conn != nil {
		c.Conn.Close()
		c.Conn = nil
	}
}

func (c *CommandClient) Send(cmd *server.Command) (err error) {
	return c.WriteJSON(cmd)
}
func (c *CommandClient) Start() {
	defer c.Close()
	// cpath:="/client"
	// if c.IsAgent {
	// 	cpath = "/agent"
	// }
	authHeader := c.makeAuthHeader()
	conn, _, err := ws.DefaultDialer.Dial(c.Address+c.path, map[string][]string{
		"Authorization": {authHeader},
	})
	if err != nil {
		panic(err)
	}
	c.Conn = conn
	c.On(util.CmdTypeMap[util.NewSession], func(args ...interface{}) {
		playload, _ := args[0].(map[string]string)
		sessionId := playload["sessionId"]
		log.Println("new session:", sessionId)
		c.SessionId = sessionId
	})
	for {
		var cmd server.Command
		err := c.ReadJSON(&cmd)
		if err != nil {
			return
		}
		eventLabel := util.CmdTypeMap[cmd.Type]
		log.Println("cmd:", cmd.Type, eventLabel)
		c.Emit(eventLabel, cmd.Payload)
	}
}

func (c *CommandClient) makeAuthHeader() string {
	a := &util.AuthEntity{
		Entity: util.Entity{
			Username: c.Username,
		},
		Time: time.Now().Unix(),
	}
	a.Authtoken = util.GenAuthToken(a, c.Salt)
	str, err := json.Marshal(a)
	if err != nil {
		panic(err)
	}
	return base64.StdEncoding.EncodeToString(str)
}

func NewClient(conf *ClientConfig) *CommandClient {
	return &CommandClient{
		ClientConfig: conf,
		EventEmitter: goemitter.NewEmitter(),
		path:         "/ws/client",
	}
}

func NewAgent(conf *ClientConfig) *CommandClient {
	return &CommandClient{
		ClientConfig: conf,
		EventEmitter: goemitter.NewEmitter(),
		path:         "/ws/agent",
	}
}
