package main

import (
	"bytes"
	"crypto/rand"
	"flag"
	"fmt"
	"io"
	mathrand "math/rand"
	"os"
	"sync"
	"time"
)

var (
	fsize int64
	count int64
	path  string
	chunk int64
)

func main() {
	flag.Int64Var(&fsize, "fsizemb", 1, "file size mb")
	flag.Int64Var(&chunk, "readsizekb", 4, "read chunk size kb")
	flag.Int64Var(&count, "count", 16, "count")
	flag.StringVar(&path, "path", "/var/www", "path")
	flag.Parse()

	fsize = fsize * 1024 * 1024
	chunk = chunk * 1024

	fmt.Printf("fsize: %d\n", fsize)
	fmt.Printf("chunk: %d\n", chunk)

	err := os.MkdirAll(path+"/files", 0755)
	if err != nil {
		panic(err)
	}

	wg := new(sync.WaitGroup)
	for i := int64(0); i < count; i++ {
		fname := fmt.Sprintf("%s/files/file_%d", path, i)
		wg.Add(1)
		go func(i int64) {
			defer wg.Done()
			manipulateFile(i, fname)
		}(i)
	}
	wg.Wait()
}

func manipulateFile(i int64, fname string) {
	file, err := os.Create(fname)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	in := io.LimitReader(rand.Reader, fsize)
	wrote, err := io.Copy(file, in)
	if err != nil {
		panic(err)
	}
	fmt.Printf("[%d]: wrote: %s: %d\n", i, fname, wrote)

	for {
		time.Sleep(time.Duration(mathrand.Intn(500)+200) * time.Millisecond)
		offset := mathrand.Int63n(fsize)
		size := chunk
		if offset+size > fsize {
			size = fsize - offset
		}
		seeked, err := file.Seek(offset, io.SeekStart)
		if err != nil {
			fmt.Printf("[%d]: seek error: %s\n", i, err)
			continue
		}
		fmt.Printf("[%d]: seek offset: %d\n", i, seeked)
		b := bytes.NewBuffer(make([]byte, 0, size))
		read, err := io.Copy(b, io.LimitReader(file, size))
		if err != nil {
			fmt.Printf("[%d]: read error: %s\n", i, err)
			continue
		}
		fmt.Printf("[%d]: read: %d\n", i, read)
	}
}
