package v1

import (
    "os"
	"net/http"
	"chain33-pai/pkg/e"
	"chain33-pai/pkg/app"
	"github.com/gin-gonic/gin"
	"chain33-pai/service/pai_service"
	"chain33-pai/pkg/setting"
	"os/exec"
	log "github.com/33cn/chain33/common/log/log15"
	"chain33-pai/pkg/util"
)

var tlog = log.New("api", "v1")

func GetDevdetail(c *gin.Context) {
	appG := app.Gin{C: c}
	var pai pai_service.Pai
	ok := pai.GetConfig()
	if !ok {
		appG.Response(http.StatusOK, e.ERROR, nil)
	}
	appG.Response(http.StatusOK, e.SUCCESS, map[string]interface{}{
		"serial": pai.Serial,
	})
}

func GetDevstatus(c *gin.Context) {
	appG := app.Gin{C: c}
	var pai pai_service.Pai
	err := pai.GetDevstatus()
	if err != nil {
		appG.Response(http.StatusOK, e.ERROR, nil)
	}
	appG.Response(http.StatusOK, e.SUCCESS, pai)
}

//获取chain33-pai程序版本
func GetPaiVersion(c *gin.Context) {
	appG := app.Gin{C:c}
	version := app.GetVersion()
	var pai pai_service.Pai

	latest,err := pai.GetPaiLatestVersion(int32(2))
	if err != nil {
		appG.Response(http.StatusOK, e.NETWORK_ERROR, nil)
		return
	}
	appG.Response(http.StatusOK, e.SUCCESS, gin.H{
		"current":version,
		"latest":latest,
	})
}

//只下载程序 重启生效
//具体更新逻辑写在代码  更新迭代比较麻烦 改为下面new方法
//下载地址阿里云oss地址  固定ip格式+/+chain33-pai+x.x.x+.tar.gz
func UpdatePai(c *gin.Context) {
	appG := app.Gin{C:c}
	if app.DPercent.Flag {
		appG.Response(http.StatusOK, e.DOWNLOAD_ERROR, "正在升级中，不要重复点击")
		return
	}
	app.DPercent.Total = int64(0)
	app.DPercent.Current = int64(0)
	var req pai_service.ReqUpdatePai
	err := c.ShouldBindJSON(&req)
	if err != nil {
		appG.Response(http.StatusOK, e.INVALID_PARAMS, nil)
		app.DPercent.Flag = false
		return
	}
	//对比版本号
	version := util.VersionCompare(app.GetVersion())
	updateversion := util.VersionCompare(req.Version)
	if updateversion <= version {
		appG.Response(http.StatusOK, e.VERSION_UPDATE_ERROR, nil)
		app.DPercent.Flag = false
		return
	}
	//检查版本号是否存在于online数据库
	var pai pai_service.Pai
	latest,err := pai.GetPaiLatestVersion(int32(2))
	if err != nil {
		appG.Response(http.StatusOK, e.DOWNLOAD_ERROR, err)
		app.DPercent.Flag = false
		return
	}

	latestversion := util.VersionCompare(latest)
	if updateversion > latestversion {
		appG.Response(http.StatusOK, e.VERSION_UPDATE_ERROR, nil)
		app.DPercent.Flag = false
		return
	}
	name := setting.Chain33Pai.Name+"_"+req.Version+".tar.gz"
	url := setting.Chain33Pai.DownloadUrl+ name
	//oss下载更新包
	err = app.DownLoadFile(url,name,int32(2))
	if err != nil {
		appG.Response(http.StatusOK, e.DOWNLOAD_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	//解压缩文件
	tar := exec.Command("tar","-xvf",name)
	err = tar.Start()
	if err != nil {
		tlog.Error("tar","err",err)
		appG.Response(http.StatusOK, e.TAR_XVF_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	err = tar.Wait()
	if err != nil {
		tlog.Error("tar","err",err)
		appG.Response(http.StatusOK, e.TAR_XVF_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	//备份原文件 确保没有alias 关联
	bak := exec.Command("cp",setting.Chain33Pai.Name,setting.Chain33Pai.Name+".bak")
	err = bak.Start()
	if err != nil {
		tlog.Error("bak","err",err)
		appG.Response(http.StatusOK, e.CP_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	err = bak.Wait()
	if err != nil {
		tlog.Error("bak","err",err)
		appG.Response(http.StatusOK, e.CP_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	//备份配置文件
	bakconf := exec.Command("cp","conf/app.ini","conf/app.ini.bak")
	err = bakconf.Start()
	if err != nil {
		tlog.Error("bakconf","err",err)
		appG.Response(http.StatusOK, e.CP_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	err = bakconf.Wait()
	if err != nil {
		tlog.Error("bakconf","err",err)
		appG.Response(http.StatusOK, e.CP_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	//替换原执行文件
	mv := exec.Command("mv",setting.Chain33Pai.Name+"_"+req.Version+"/"+setting.Chain33Pai.Name,".")
	err = mv.Start()
	if err != nil {
		tlog.Error("mv","err",err)
		appG.Response(http.StatusOK, e.MV_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	err = mv.Wait()
	if err != nil {
		tlog.Error("mv","err",err)
		appG.Response(http.StatusOK, e.MV_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	//替换配置文件
	mvconf := exec.Command("mv",setting.Chain33Pai.Name+"_"+req.Version+"/conf/app.ini","conf")
	err = mvconf.Start()
	if err != nil {
		tlog.Error("mvconf","err",err)
		appG.Response(http.StatusOK, e.MV_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	err = mvconf.Wait()
	if err != nil {
		tlog.Error("mvconf","err",err)
		appG.Response(http.StatusOK, e.MV_ERROR, err)
		app.DPercent.Flag = false
		return
	}
    os.RemoveAll("scripts")
	os.Mkdir("scripts",0600)
	//删除temp文件夹
	//替换原执行文件
	app.MVScripts(setting.Chain33Pai.Name+"_"+req.Version,".")

	remove := exec.Command("rm","-rf",setting.Chain33Pai.Name+"_"+req.Version,name)
	err = remove.Start()
	if err != nil {
		appG.Response(http.StatusOK, e.RM_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	err = remove.Wait()
	if err != nil {
		appG.Response(http.StatusOK, e.RM_ERROR, err)
		app.DPercent.Flag = false
		return
	}
	app.DPercent.Flag = false
	appG.Response(http.StatusOK, e.SUCCESS, nil)
}

//只下载程序 不必关心具体的更新内容 配置文件通用 重启生效
//忽略req.Version 对比自己版本和最新版本 直接更新覆盖最新版本
//下载地址阿里云oss地址  固定ip格式+/+chain33-pai+x.x.x+.tar.gz
func UpdatePaiNew(c *gin.Context) {
	appG := app.Gin{C:c}
	if app.DPercent.Flag {
		appG.Response(http.StatusOK, e.DOWNLOAD_ERROR, "正在升级中，不要重复点击")
		return
	}
	app.DPercent.Flag = true
	app.DPercent.Total = int64(0)
	app.DPercent.Current = int64(0)
	var req pai_service.ReqUpdatePai
	err := c.ShouldBindJSON(&req)
	if err != nil {
		appG.Response(http.StatusOK, e.INVALID_PARAMS, nil)
		app.DPercent.Flag = false
		return
	}
	err = app.AutoUpdatePai()
	if err != nil {
		app.DPercent.Flag = false
		appG.Response(http.StatusOK, e.VERSION_UPDATE_ERROR, nil)
		return
	}

	app.DPercent.Flag = false
	appG.Response(http.StatusOK, e.SUCCESS, nil)
}


func GetDPercent(c *gin.Context) {
	appG := app.Gin{C:c}
	appG.Response(http.StatusOK, e.SUCCESS, gin.H{
		"total":app.DPercent.Total,
		"current":app.DPercent.Current,
	})
}

func GetExternal(c *gin.Context) {
	appG := app.Gin{C:c}
	ip,err := util.GetExternal()
	if err != nil {
		appG.Response(http.StatusOK, e.ERROR, "get external ip err")
		return
	}
	appG.Response(http.StatusOK, e.SUCCESS, ip)
}

func GetServerStatus(c *gin.Context) {
	appG := app.Gin{C:c}
	err := app.MonitorServer()
	if err != nil {
		appG.Response(http.StatusOK, e.ERROR, err)
		return
	}
	appG.Response(http.StatusOK, e.SUCCESS, app.ServerStatus)
}