package client

import (
	"net"
	"sync"
	"time"

	"github.com/adamweixuan/getty"

	"virjar.com/majora-go/infra"
	"virjar.com/majora-go/log"
	"virjar.com/majora-go/model"
	"virjar.com/majora-go/safe"
)

type Client struct {
	config *model.Configure

	localAddr    net.Addr
	natTunnel    getty.Client
	connStore    sync.Map
	sessionStore sync.Map
}

func NewClientWithConf(cfg *model.Configure) *Client {
	return NewCli(cfg)
}

func NewCli(cfg *model.Configure) *Client {
	var localAddr net.Addr
	if len(cfg.LocalAddr) > 0 {
		localAddr = &net.TCPAddr{
			IP:   net.ParseIP(cfg.LocalAddr),
			Port: 0,
		}
	}
	client := &Client{
		config:       cfg,
		localAddr:    localAddr,
		connStore:    sync.Map{},
		sessionStore: sync.Map{},
	}

	return client
}

func (client *Client) StartUp() {
	client.check()
	client.connect()
}

func (client *Client) check() {
	cfg := client.config

	if !cfg.Redial.Valid() {
		return
	}
	interval := cfg.NetCheckInterval
	if interval <= 0 {
		interval = time.Second * 5
	}

	url := infra.RandUrl()
	if len(cfg.NetCheckUrl) > 0 {
		url = cfg.NetCheckUrl
	}

	safe.SageGo(func() {
		var timer = time.NewTimer(interval)
		for {
			timer.Reset(interval)
			<-timer.C
			success := infra.Ping(url)
			if success {
				continue
			}
			log.Run().Warnf("net check fail, redial...")
			infra.RedialByCheck(cfg)
		}
	})
}
