package app

import (
	"chain33-pai/models"
	"chain33-pai/pkg/setting"
	"fmt"
	"bytes"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"sync"
	"time"
	"strings"
	"chain33-pai/pkg/util"
)

func GennerPort()(port,daemonPort int,err error){
	for{
		var flag bool
		var buf bytes.Buffer
		rand.Seed(time.Now().Unix())
		port=rand.Intn(65535)
		rand.Seed(time.Now().Unix())
		daemonPort=rand.Intn(55535)
		ss:=exec.Command(setting.Chain33Pai.SS,fmt.Sprint(port))
		ss.Stdout=&buf
		err=ss.Start()
		if err!=nil{
			log.Println(err)
			return

		}
		ss.Wait()
		if err!=nil{
				log.Println(err)
				return
		}

		//为空代表端口未被占用
		if buf.String()==""{
			log.Println(port)
			flag=true
		}
		ss=exec.Command(setting.Chain33Pai.SS,fmt.Sprint(daemonPort))
		ss.Stdout=&buf
		err=ss.Start()
		if err!=nil{
			log.Println(err)
			return
		}
		ss.Wait()
		if err!=nil{
			log.Println(err)
			return
		}

		//守护端口和通信端口都未被占用的情况下返回
		if buf.String()==""&&flag{
			log.Println(port)
			//fmt.Println("finish")
			return
		}
	}
}

var mu sync.Mutex
func AppendKeyPair(keyPair string){
	mu.Lock()
	defer mu.Unlock()
	f,err:=os.OpenFile(fmt.Sprintf("%s/authorized_keys",setting.Chain33Pai.SSH),os.O_WRONLY|os.O_APPEND,0600)
	defer f.Close()
	if err!=nil{
		log.Println(err)
		return
	}
	f.WriteString(keyPair)
}
func Preprocessing(){//判断密钥对是否存在,存在则删除
	_, err := os.Stat(setting.Chain33Pai.SSH)
	if err == nil || os.IsExist(err){
		err=os.RemoveAll(setting.Chain33Pai.SSH)
		fmt.Println(err)
	}
}

func reKeygen(){
	Preprocessing()
	ssh_keygen:=exec.Command(setting.Chain33Pai.Keygen)
	ssh_keygen.Start()
	ssh_keygen.Wait()
	f,_:=os.OpenFile("authorized_keys",os.O_CREATE,0600)
	f.Close()

}

func CleanUp1(){
	var buff bytes.Buffer
	netstat:=exec.Command(setting.Chain33Pai.NetStat)
	netstat.Stdout=&buff
	idSelector:=strings.Split(buff.String(),"\n")
	if len(idSelector)==0{//没有映射端口存在，即没有需要处理的反馈
		reKeygen()//清空authorized_keys
		models.DropFeedBack()//清空数据库记录
		return
	}
	for _,v:=range idSelector{
		if models.IsComplete(v){
			models.DelFeedBack(v)
		}
	}
}

func CleanUp(){
	list,err := models.GetAllFeedBackList()
	if err != nil {
		fmt.Println("GetAllFeedBackList",err)
	}
	fmt.Println("GetAllFeedBackList",list)
	//var buff bytes.Buffer
	//netstat:=exec.Command(setting.Chain33Pai.NetStat)
	//netstat.Stdout=&buff
	//idSelector:=strings.Split(buff.String(),"\n")
	//if len(list)==0{//没有映射端口存在，即没有需要处理的反馈
	//	reKeygen()//清空authorized_keys
	//	return
	//}
	models.DeleteCompleteFeedback()
}

//清除已解决反馈
func CleanUpNossh(){
	list,err := models.GetAllFeedBackListNossh()
	if err != nil {
		fmt.Println("GetAllFeedBackListNossh",err)
	}
	fmt.Println("GetAllFeedBackListNossh",list)

	models.DeleteCompleteFeedbackNossh()
}

func CornDayJob(ticker *time.Ticker){
	for{
		select {
		case <-ticker.C:
			CleanUp()
			//CleanUpNossh()
			//CreateMonthTable()
		}
	}
}

func CornData(ticker *time.Ticker){
	for{
		select {
		case <-ticker.C:
			UploadMinerData()
			SendMailIfNodeError()
		}
	}
}

func UploadMinerData() bool {
	count,err := models.GetTicketSum()
	if err != nil {
		fmt.Println("GetTicketSum",err)
		return false
	}
	isok := models.UpdateMinerData(models.RaspMinerData{TicketCount:count})
	if isok {
		fmt.Println("UpdateMinerData ok")
		return true
	} else {
		fmt.Println("UpdateMinerData fail")
		return false
	}

}

func SendMailIfNodeError() error {
	list,err := models.GetAllDevList()
	if err != nil {
		fmt.Println("GetAllDevList",err)
		return err
	}

	for _, v:= range list {
		if v.NodeStatus == 1 {
			continue
		}
		//一天只发一次
		if !models.CheckEmailToday(&models.RaspEmailHistory{Addr:v.Addr,Date:util.GetMonthDay()}) {
			continue
		}
		if v.NodeStatus == 0 && v.Email != "" {//节点未启动
			fmt.Println(NODEERROR,"addr=",v.Addr,"email=",v.Email)
			JobChan <- MsgType{Name:NODEERROR,Email:v.Email}
			continue
		}
		if (time.Now().Unix() - v.UpdateTime) > 600 && v.Email != "" {//超过10分钟未上传数据
			fmt.Println(NETWORKERROR,"addr=",v.Addr,"email=",v.Email)
			JobChan <- MsgType{Name:NETWORKERROR,Email:v.Email}
		}
		two,err := models.GetDevList(models.RaspDevListQuery{Addr:v.Addr,Page:2})
		if err != nil {
			fmt.Println("GetDevList",err)
			continue
		}
		if len(two) == 2 {
			if two[0].Height == two[1].Height && v.Height != 0 && v.Email != "" {
				fmt.Println(NODENOTSYNC,"addr=",v.Addr,"email=",v.Email)
				JobChan <- MsgType{Name:NODENOTSYNC,Email:v.Email}
			}
		}
	}
	return nil
}


func CreateMonthTable() error {
	return models.CreateMonthDevHistoryTable()
}