package server

import (
	"net/http"

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

type Pipe struct {
	Id       string
	Src      string
	Dst      string
	src      *websocket.Conn
	dst      *websocket.Conn
	stopChan chan int
}

func (p *Pipe) Start() {
	p.stopChan = make(chan int)
	go p.forward(p.src, p.dst)
	go p.forward(p.dst, p.src)
	<-p.stopChan
	p.src.Close()
	p.dst.Close()
}
func NewPipe(src, dst string) *Pipe {
	return &Pipe{
		Id:  util.GenRandomstring(16),
		Src: src,
		Dst: dst,
	}

}

func (p *Pipe) forward(src, dst *websocket.Conn) {
	for {
		mtype, message, err := src.ReadMessage()
		if err != nil {

			break
		}
		err = dst.WriteMessage(mtype, message)
		if err != nil {

			break
		}
	}
	p.stopChan <- 1
}

func (s *Server) HandlePipe(conn *websocket.Conn, r *http.Request) {
	session := r.Header.Get("Session")
	if session == "" {
		s.logger.Error("no session header")
		conn.Close()
		return
	}
	cmdSession := s.findSession(session)
	if cmdSession == nil {
		conn.Close()
		s.logger.Error("command session not found")
		return
	}
	lpath := r.URL.Path
	pipeId := lpath[len("/ws/pipe/"):]
	pipe, ok := s.pipes[pipeId]

	if !ok {
		conn.Close()
		s.logger.Error("pipe not found")
		cmdSession.Send(NewErrorResponse("pipe not found", nil))
		return
	}

	if pipe.Src == session {
		pipe.src = conn
	} else if pipe.Dst == session {
		pipe.dst = conn
	} else {
		cmdSession.Send(NewErrorResponse("not endpoint of current pipe", nil))
		conn.Close()
		return
	}

	if pipe.src != nil && pipe.dst != nil {
		go pipe.Start()
		clientCmdSession := s.findSession(pipe.Src)
		clientCmdSession.Send(NcmdConnectionReady(pipe.Id)) // info src endpoint ready and can setup proxy listener
	}
}

func (s *Server) findSession(sessionId string) *Session {
	clientSession, ok := s.clientSession[sessionId]
	if ok {
		return clientSession
	}
	agentSession, ok := s.agentSession[sessionId]
	if ok {
		return agentSession
	}
	return nil
}
