package main

import (
	"net"
	"sync"

	"net/http"

	"./log"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
)

var (
	upgrader = &websocket.Upgrader{
		ReadBufferSize:  SYS_BUF_SIZE,
		WriteBufferSize: SYS_BUF_SIZE,
	}
)

func NewWsAcceptor(log *log.Logger, onAccept func(conn net.Conn)) Acceptor {
	return &wsAcceptor{
		log:        log,
		onAccept:   onAccept,
		blockIPMap: map[string]int64{},
	}
}

type wsAcceptor struct {
	sync.Mutex
	log        *log.Logger // 日志
	onAccept   func(conn net.Conn)
	isRunning  bool // 是否在运行
	blockIPMap map[string]int64
	listener   net.Listener
	close      chan struct{} // 执行退出
	closeDone  chan struct{} // 用于同步退出完成
	server     *http.Server
}

func (self *wsAcceptor) Start(addr string) error {
	self.Lock()
	defer self.Unlock()

	if self.isRunning {
		return nil
	}

	router := mux.NewRouter()
	router.HandleFunc("/", self.do_homepage)
	router.HandleFunc("/gate", self.do_accept)

	self.server = &http.Server{
		Addr:    addr,
		Handler: router,
	}
	ln, err := listen(addr)
	if err != nil {
		self.log.Error("listen failed", zap.String("addr", addr), zap.Error(err))
		return err
	}

	self.close = make(chan struct{})
	self.closeDone = make(chan struct{})
	self.isRunning = true
	self.listener = ln

	return self.server.Serve(ln)
}

func (self *wsAcceptor) Close() {
	select {
	case <-self.close:
		return
	default:
	}
	close(self.close)
	self.listener.Close()
	<-self.closeDone
}

func (self *wsAcceptor) do_homepage(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method now allowed", http.StatusMethodNotAllowed)
		return
	}
	w.Write([]byte("welcome " + NAME + " v" + VERSION))
}

func (self *wsAcceptor) do_accept(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if nil != err {
		self.log.Warn("upgrade failed", zap.Error(err))
		return
	}

	wsconn := NewWsConn(conn)
	self.onAccept(wsconn)
}
