package version

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"runtime"
	"strings"
)

const verURI = "https://downloads.leap.se/RiseupVPN/"

// CanUpgrade returns true if there's a newer version string published on the server
// this needs to manually bump latest version for every platform in the
// downloads server.
// at the moment, we hardcode RiseupVPN in the path, assuming that all clients
// stay in sync.
func CanUpgrade() bool {
	if os.Getenv("SKIP_VERSION_CHECK") == "1" {
		return false
	}
	log.Println("Checking for updates...")
	uri := verURI
	switch runtime.GOOS {
	case "windows":
		uri += "windows"
	case "darwin":
		uri += "osx"
	case "linux":
		fallthrough
	default:
		uri += "linux"
	}
	uri += "/lastver"
	resp, err := http.Get(uri)
	if err != nil {
		log.Println(err)
		return false
	}
	defer resp.Body.Close()
	verStr, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return false
	}
	r := strings.TrimSpace(string(verStr))
	if strings.Count(r, "\n") > 1 {
		log.Println("No remote version found at " + uri)
		return false
	}
	canUpgrade := versionOrdinal(r) > versionOrdinal(VERSION)
	if os.Getenv("DEBUG") == "1" {
		log.Println(">>> Remote version:  " + r)
		log.Println(">>> Current version: " + VERSION)
	}
	if canUpgrade {
		log.Println("There's a newer version available:", r)
	}
	return canUpgrade
}

// https://stackoverflow.com/a/18411978
func versionOrdinal(version string) string {
	const maxByte = 1<<8 - 1
	vo := make([]byte, 0, len(version)+8)
	j := -1
	for i := 0; i < len(version); i++ {
		b := version[i]
		if '0' > b || b > '9' {
			vo = append(vo, b)
			j = -1
			continue
		}
		if j == -1 {
			vo = append(vo, 0x00)
			j = len(vo) - 1
		}
		if vo[j] == 1 && vo[j+1] == '0' {
			vo[j+1] = b
			continue
		}
		if vo[j]+1 > maxByte {
			log.Println("VersionOrdinal: invalid version")
			return string(vo)
		}
		vo = append(vo, b)
		vo[j]++
	}
	return string(vo)
}
