package storage

import (
	"io"
	"io/ioutil"
	"http"
	"log"
	"strconv"
	"strings"
)

type Needle struct {
	Cookie       uint8  "random number to mitigate brute force lookups"
	Key          uint64 "file id"
	AlternateKey uint32 "supplemental id"
	Size         uint32 "Data size"
	Data         []byte "The actual file data"
	Checksum     int32  "CRC32 to check integrity"
	Padding      []byte "Aligned to 8 bytes"
}

func NewNeedle(r *http.Request) (n *Needle) {
	n = new(Needle)
	form, fe := r.MultipartReader()
	if fe != nil {
		log.Fatalf("MultipartReader [ERROR] %s\n", fe)
	}
	part, _ := form.NextPart()
	data, _ := ioutil.ReadAll(part)
	n.Data = data

	n.ParsePath(r.URL.Path[1:strings.LastIndex(r.URL.Path, ".")])

	return
}
func (n *Needle) ParsePath(path string) {
	a := strings.Split(path, "_")
	log.Println("cookie", a[0], "key", a[1], "altKey", a[2])
	cookie, _ := strconv.Atoi(a[0])
	n.Cookie = uint8(cookie)
	n.Key, _ = strconv.Atoui64(a[1])
	altKey, _ := strconv.Atoui64(a[2])
	n.AlternateKey = uint32(altKey)
}
func (n *Needle) Append(w io.Writer) {
	header := make([]byte, 17)
	header[0] = n.Cookie
	uint64toBytes(header[1:9], n.Key)
	uint32toBytes(header[9:13], n.AlternateKey)
	n.Size = uint32(len(n.Data))
	uint32toBytes(header[13:17], n.Size)
	w.Write(header)
	w.Write(n.Data)
	rest := 8 - ((n.Size + 17 + 4) % 8)
	uint32toBytes(header[0:4], uint32(n.Checksum))
	w.Write(header[0 : rest+4])
}
func (n *Needle) Read(r io.Reader, size uint32) {
	bytes := make([]byte, size+17+4)
	r.Read(bytes)
	n.Cookie = bytes[0]
	n.Key = bytesToUint64(bytes[1:9])
	n.AlternateKey = bytesToUint32(bytes[9:13])
	n.Size = bytesToUint32(bytes[13:17])
	n.Data = bytes[17 : 17+size]
	n.Checksum = int32(bytesToUint32(bytes[17+size : 17+size+4]))
}