package fllcc

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"math/rand"
	"net"
	"net/url"
	"strings"
	"time"
)

var random *rand.Rand

func init() {
	random = rand.New(rand.NewSource(time.Now().Unix()))
}

func getFreePort() (int, error) {
	for i := 4000; i <= 5000; i++ {
		if portIsFree(i) {
			return i, nil
		}
	}

	return 0, errors.New("没有可用端口")
}

func portIsFree(checkPort int) bool {
	addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("localhost:%d", checkPort))
	if err != nil {
		return false
	}

	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return false
	}

	defer l.Close()
	return true
}

func urlToABS(base, reference string) (string, error) {
	u, err := url.Parse(reference)
	if err != nil {
		return "", err
	}

	baseUrl, err := url.Parse(base)
	if err != nil {
		return "", err
	}

	return baseUrl.ResolveReference(u).String(), nil
}

func DescData(content string, secretKey string) (string, error) {
	return descData(content, secretKey)
}

func descData(content string, secretKey string) (string, error) {
	lockStream := "GHI9+JKLxyz012MNOPYbcRSTUVW8/ABCw3DEZaFXefghijklm7=nopqrsdQtuv456"
	lockLen := len(lockStream)
	enLend := len(content)
	randomLock := string([]rune(content)[enLend-1])
	lockCount := strings.Index(lockStream, randomLock)
	password := getMD5Hash(secretKey + randomLock)
	txtStream := content[0 : enLend-1]
	tmpStream := ""
	k := 0

	for i := 0; i < len(txtStream); i++ {
		if k == len(password) {
			k = 0
		}

		pwdInt := password[k]
		findStr := string([]rune(txtStream)[i])
		j := strings.Index(lockStream, findStr) - lockCount - int(pwdInt)
		for {
			if j >= 0 {
				break
			}

			j += lockLen
		}

		tmpStream += string([]rune(lockStream)[j])
		k++
	}

	byteList, err := base64.StdEncoding.DecodeString(tmpStream)
	if err != nil {
		return "", err
	}

	return string(byteList), nil
}

func EncData(txtStream string, secretKey string) (string, error) {
	password := secretKey
	lockstream := "GHI9+JKLxyz012MNOPYbcRSTUVW8/ABCw3DEZaFXefghijklm7=nopqrsdQtuv456"

	//随机找一个数字，并从密锁串中找到一个密锁值
	lockLen := len(lockstream)
	lockCount := random.Int31n(int32(lockLen))

	randomLock := string([]rune(lockstream)[lockCount])
	password = getMD5Hash(password + randomLock)
	txtStream = base64.StdEncoding.EncodeToString([]byte(txtStream))
	tmpStream := ""
	j := 0
	k := 0

	for i := 0; i < len(txtStream); i++ {
		if k == len(password) {
			k = 0
		}

		findChar := string([]rune(txtStream)[i])
		j = (strings.Index(lockstream, findChar) + int(lockCount) + int(password[k])) % lockLen
		tmpStream += string([]rune(lockstream)[j])

		k++
	}

	return tmpStream + randomLock, nil
}

func getMD5Hash(text string) string {
	hash := md5.Sum([]byte(text))
	return hex.EncodeToString(hash[:])
}

func outputLog(v ...interface{}) {
	logStr := fmt.Sprintln(v...)
	log.Println(logStr)
	//_, _ = logBuffer.Write([]byte(logStr))
}
