/**
 * @desc		TCP框架
 * ********************************************
 * @author		unphp <unphp@qq.com>
 * @date		2021-12-17
 * @copyright	ants 0.1
 * ********************************************
 */

package ants

import (
	"PPOSUtils/utils"
	"net"
	"os"
	"strings"
	"sync/atomic"
	"time"
)

type ServerConfig struct {
	Address  string `yaml:"ants_address"`   // ip地址与端口，例：127.0.0.1:11086
	Auth     string `yaml:"ants_auth"`      // 验密，例：username@password
	MaxChild int    `yaml:"ants_max_child"` // 最大请求数，例：1000
}

func NewServer(config ServerConfig) *Server {
	_address := strings.Split(config.Address, ":")
	_auth := strings.Split(config.Auth, "@")
	return &Server{
		mode:         "tcp",
		host:         _address[0],
		port:         utils.ToInt(_address[1]),
		user:         _auth[0],
		password:     _auth[1],
		poolMaxNum:   config.MaxChild,
		poolNum:      10,
		outReadTime:  10,
		outWriteTime: 5,
		readDeadline: time.Duration(5) * time.Second,
		router:       NewRouter(),
	}
}

//Server TCP服务
type Server struct {
	mode            string
	host            string //主机ip
	port            int    //端口
	outReadTime     int64
	outWriteTime    int64
	user            string
	password        string
	poolMaxNum      int
	poolNum         int           //
	readDeadline    time.Duration //
	router          RouterInterface
	leaderCheckFunc func() bool
	leaderFunc      func() string
}

//Router 路由器
func (that *Server) Router() RouterInterface {
	return that.router
}

//AddRouter 注册路由匹配命中的"处理方法"
func (that *Server) AddRouter(path string, router Handler) *Server {
	that.router.AddRouter(path, router)
	return that
}

//AddGroup 注册路由分组
func (that *Server) AddGroup(path string) RouterInterface {
	return that.router.AddGroup(path)
}

func (that *Server) SetStartPoolNum(i int) *Server {
	that.poolNum = i
	return that
}

func (that *Server) SetMaxPoolNum(i int) *Server {
	that.poolMaxNum = i
	return that
}

func (that *Server) GetPoolNum() int {
	return that.poolNum
}

func (that *Server) SetDefaultDeadline(t time.Duration) *Server {
	that.readDeadline = t
	return that
}

//LeaderCheck 分布式节点中，检测当前的服务是否为leader
func (that *Server) LeaderCheck() bool {
	if that.leaderCheckFunc != nil {
		return that.leaderCheckFunc()
	}
	return false
}

func (that *Server) Leader() string {
	if that.leaderFunc != nil {
		return that.leaderFunc()
	}
	return ""
}

//SetLeaderCheckFunc 分布式节点中，设置"检测leader"的方法
func (that *Server) SetLeaderCheckFunc(check func() bool) *Server {
	that.leaderCheckFunc = check
	return that
}

//SetLeaderFunc ...
func (that *Server) SetLeaderFunc(leader func() string) *Server {
	that.leaderFunc = leader
	return that
}

//Run 开始启动TCP Socket服务
func (that *Server) Run() {
	_tcpAddr := &net.TCPAddr{
		IP:   net.ParseIP(that.host),
		Port: that.port,
		Zone: that.mode,
	}
	_listener, _err := net.ListenTCP("tcp", _tcpAddr)
	if _err != nil {
		os.Exit(1)
	}
	//log.Info("*****************************************************")
	log.Infof("AntsServer running, bind port: %d", that.port)
	//log.Info("*****************************************************")
	defer _listener.Close()
	_connChan := make(chan *net.TCPConn)
	//预开启子协程
	for i := 0; i < that.poolNum; i++ {
		go func() {
			for _tcpConn := range _connChan {
				_transfer := new(Transfer)
				_transfer.tcpConn = _tcpConn
				_transfer.request = func() *Request {
					return NewRequest(that.router)
				}
				_transfer.clusterCheck = that
				_transfer.outReadTime = that.outReadTime
				_transfer.outWriteTime = that.outWriteTime
				_transfer.user = that.user
				_transfer.password = that.password
				_transfer.Transport()
				_transfer.Close()
				log.Debugf("conn[%s] closed", _transfer.clientID)
				_transfer = nil
			}
		}()
	}
	poolNum := int64(that.poolNum)
	poolMaxNum := int64(that.poolMaxNum)
	//开始监听
	for {
		_tcpConn, _err := _listener.AcceptTCP()
		if _err != nil {
			return
		}
		//通过信道，转交给预开启的子协程处理，达到非阻塞监听处理请求
		select {
		case _connChan <- _tcpConn:
			//
		default:
			if poolNum < poolMaxNum {
				log.Warnf("dynamic add conn(%d)", poolNum)
				atomic.AddInt64(&poolNum, 1)
				go func() {
					defer func() {
						atomic.AddInt64(&poolNum, -1)
					}()
					_transfer := new(Transfer)
					_transfer.tcpConn = _tcpConn
					_transfer.request = func() *Request {
						return NewRequest(that.router)
					}
					_transfer.clusterCheck = that
					_transfer.outReadTime = that.outReadTime
					_transfer.outWriteTime = that.outWriteTime
					_transfer.user = that.user
					_transfer.password = that.password
					_transfer.Transport()
					_transfer.Close()
					log.Debugf("conn[%s] closed", _transfer.clientID)
					_transfer = nil
				}()
				poolNum--
			} else {
				//超过限制，直接关闭拒绝链接
				log.Warnf("the conn request exceeding maximum(%d) limit", poolMaxNum)
				_tcpConn.Close()
			}
		}

	}

}
