package utils

import (
	"fmt"
	"io"
	"log"
	"math/rand"
	"os"
	"strings"
	"time"
)

func PrintElapsed(start time.Time) {
	fmt.Fprintf(os.Stderr, "%s+~+~+", time.Now().Sub(start))
}

func Copy(src, dest string) {
	s, err := os.Open(src)
	defer s.Close()
	if err != nil {
		log.Fatalf("\nFailed to open file at %s\n%s\n", src, err)
	}

	d, err := os.Create(dest)
	defer d.Close()
	if err != nil {
		log.Fatalf("\nFailed to open file at %s\n%s\n", dest, err)
	}

	buf := make([]byte, 256)
	for {
		n, err := s.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatalf("\nFailed to read file during copy at %s\n%s\n", src, err)
		}
		if n == 0 {
			break
		}

		if _, err := d.Write(buf[:n]); err != nil {
			log.Fatalf("\nFailed to write file at %s\n%s\n", dest, err)
		}
	}
}

func AcceptQuotedText(str string) string {
	if len(str) < 1 {
		return str
	}
	if str[0] == '"' {
		str = str[1:]
	}
	if str[len(str)-1] == '"' {
		str = str[:len(str)-1]
	}
	return str
}

func ComputeHash(numLetters, numDigits int) string {
	return strings.Join(shuffle(strings.Split(fmt.Sprintf("%s%s", RandLetters(numLetters), RandDigits(numDigits)), "")), "")
}

func shuffle(src []string) []string {
	final := make([]string, len(src))
	rand.Seed(time.Now().UTC().UnixNano())
	perm := rand.Perm(len(src))

	for i, v := range perm {
		final[v] = src[i]
	}
	return final
}

func RandChars(n int) string {
	const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"

	rand.Seed(time.Now().UnixNano())

	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}

	return string(b)
}

func RandLetters(n int) string {
	const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

	rand.Seed(time.Now().UnixNano())

	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}

	return string(b)
}

func RandDigits(n int) string {
	const letterBytes = "1234567890"

	rand.Seed(time.Now().UnixNano())

	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}

	return string(b)
}

func TruncateStringWhitespace(str string) string {
	var prev byte
	var newStr = ""

	for i := 0; i < len(str); i++ {
		ch := str[i]

		if prev == '\n' && ch == '\n' {
			continue
		}

		if prev == '\n' && ch == '\t' {
			continue
		}

		if prev == '\n' && ch == ' ' {
			continue
		}

		if prev == '\t' && ch == '\t' {
			continue
		}

		if prev == ' ' && ch == ' ' {
			continue
		}

		if ch == '\r' {
			continue
		}

		prev = ch

		newStr += string(ch)
	}

	return newStr
}
