package controller

import (
	"backend/model"
	"fmt"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"time"

	"github.com/labstack/echo/v4"
	"github.com/sirupsen/logrus"
	"github.com/spf13/viper"
)

// 如果没有对应文件夹就建立
func catalogBuild(fileType string) error {
	err := os.Mkdir("pastebin/backend/files/"+fileType, 0666)
	if err != nil {
		return err
	}
	return nil
}

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

/*
 * generate new uuid
 */
func IdGen(n int) string {
	b := make([]rune, n)
	rand.Seed(time.Now().UnixNano())
	//for i:=0;i<n;i++{
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

/*
 * 新建一个sid和url的关联，并返回一个bool表示成功与否
 * 若无sessionId，生成一个八位sid并返回
 */
func newAuthenticate(sid string, url string, passwd string, time time.Time) (rsid string, stat uint) {
	if sid == "" {
		rsid = IdGen(8)
	} else {
		rsid = sid
	}
	stat = model.Createlink(rsid, passwd, url, time)
	return rsid, stat
}

/*
 * 判断用户有无权限访问
 * sid 用cookie 储存传输，如果新生成sid，则保存至cookie
 */
func Autheticate(cookie *http.Cookie, url string, passwd string, time time.Time) uint {
	sid := cookie.Value
	if model.Find(sid, url) {
		return 1 // 鉴权通过
	} else {
		var stat uint
		sid, stat = newAuthenticate(sid, url, passwd, time)
		cookie.Value = sid
		return stat
	}
}

/*
 * 通过文件扩展名获取ContentType
 */
func GetFileContentType(fileType string) string {
	var StrRet string = ""
	switch fileType {
	case ".txt":
		StrRet = "text/plain"
	case ".csv":
		StrRet = "text/csv"
	case ".tex":
		StrRet = "application/x-tex"
	case ".md":
		StrRet = "text/x-markdown"
	}
	return StrRet
}

// 设置cookie name sid, value link
func SetCookie(c echo.Context, cookie *http.Cookie, sid string, maxAge int, time_ time.Time) error {
	cookie.Name = "User" // 标识为user
	//cookie.Value = string(uuid)  // 通过uuid和数据库，确定user是谁
	cookie.Value = sid
	cookie.Path = "/"
	// cookie有效期为3600秒
	if maxAge == 0 {
		if time_.IsZero() {
			cookie.MaxAge = 3600
		} else {
			cookie.MaxAge = int(time.Until(time_).Seconds())
			if cookie.MaxAge <= 0 {
				cookie.MaxAge = 3600
			}
		}
	} else {
		cookie.MaxAge = maxAge
	}
	// 设置cookie
	c.SetCookie(cookie)
	return nil
}

func srcRead(c echo.Context, info *File) (src multipart.File, err error) {
	file, err := c.FormFile("file")
	if err != nil {
		logrus.Println(err)
		return nil, err
	}

	// 打开用户上传的文件
	src, err = file.Open()
	if err != nil {
		logrus.Println(err)
		return nil, err
	}
	defer src.Close()

	if err = c.Bind(info); err != nil {
		logrus.Println(err)
		return nil, err
	}
	info.FileName = file.Filename

	return src, nil
}

func dstCreate(info *File) (dst *os.File, filePath string) {
	info.FileType = TypeComplement(info.FileType)
	filePath = "./files/" + info.FileType + "/" + info.FileName
	dst, err := os.Create(filePath)
	if err != nil {
		// 是否目录不完整引起的问题
		if !os.IsExist(err) {
			if catalogBuild(info.FileType) != nil {
				logrus.Println(err)
				return nil, ""
			}
			dst, err = os.Create(filePath)
			if err != nil {
				logrus.Println(err)
				return nil, ""
			}
		}
	}
	return dst, filePath
}

/*
 * 判断文件大小是否超过阈值(threshold,单位B)
 */
func overflow(dst *os.File, threshold int64) bool {
	// 获取文件大小，
	fi, err := dst.Stat()
	if err != nil {
		logrus.Println(err)
	}

	// 大小比较
	if fi.Size() > threshold {
		return false
	} else {
		return true
	}

}

func DBupdate(c echo.Context, filePath string, info *File) (string, string) {
	url := "http://pastebin/" + IdGen(8)
	cookie, _ := c.Cookie("User")
	var sid string
	if cookie == nil {
		sid = ""
	} else {
		sid = cookie.Value
	}
	sid, _ = newAuthenticate(sid, url, info.Url, info.Time)
	model.CreatelinkFirstTime(sid, url, info.Time)
	if info.MaxAccess == 0 {
		//num,_=strconv.ParseUint(GetSetting("maxDefaultAccess"), 10, 64)
		info.MaxAccess = 30 // 设置最大默认可访问次数
	}
	model.Savetext(filePath, info.MaxAccess, info.Passwd, info.Time, url)
	return sid, url
}

func readFile(filePath string) string {
	src, err := os.Open(filePath)
	if err != nil {
		fmt.Println(err)
	}
	fi, err := src.Stat()
	if err != nil {
		fmt.Println(err)
	}

	defer func() {
		src.Close()
	}()

	data := make([]byte, fi.Size())
	_, err = src.Read(data)
	if err != nil {
		fmt.Println(err)
	}
	// 信息隐去
	//c.JSON(http.StatusOK, info)

	return string(data)
}

// 格式化后缀，仿止出错
func TypeComplement(typ string) string {
	// 类型判断
	if typ == "" {
		typ = ".txt"
	} else if typ[0] != '.' {
		typ = "." + typ
	}
	return typ
}

/*
 * 没有设定过期时间，oriTime 为 0
 * 此函数将默认过期时间设为当前时间后半小时
 */
func timeAssign(oriTime time.Time) time.Time {
	if oriTime.IsZero() {
		return time.Now().Add(30 * time.Minute)
	} else {
		return oriTime
	}
}

func GetSetting(key string) (value string) {
	// config
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("./")
	err := viper.ReadInConfig()
	if err != nil {
		logrus.Panic(err)
	}
	// connect to database
	logInfo := viper.GetStringMapString("setting")
	return logInfo[key]
}
