package azure

import (
	"bytes"
	"io"
)

type blockBlobWriter interface {
	GetSize(container, blob string) (int64, error)
	WriteBlobAt(container, blob string, offset int64, chunk io.Reader) (int64, error)
}

// zeroFillWriter enables writing to an offset outside a block blob's size
// by offering the chunk to the underlying writer as a contiguous data with
// the gap in between filled with NUL (zero) bytes.
type zeroFillWriter struct {
	blockBlobWriter
}

func newZeroFillWriter(b blockBlobWriter) zeroFillWriter {
	w := zeroFillWriter{}
	w.blockBlobWriter = b
	return w
}

// Write writes the given chunk to the specified existing blob even though
// offset is out of blob's size. The gaps are filled with zeros. Returned
// written number count does not include zeros written.
func (z *zeroFillWriter) Write(container, blob string, offset int64, chunk io.Reader) (int64, error) {
	size, err := z.blockBlobWriter.GetSize(container, blob)
	if err != nil {
		return 0, err
	}

	var reader io.Reader
	var zeroPadding int64
	if offset <= size {
		reader = chunk
	} else {
		zeroPadding = offset - size
		offset = size // adjust offset to be the append index
		zeros := bytes.NewReader(make([]byte, zeroPadding))
		reader = io.MultiReader(zeros, chunk)
	}

	nn, err := z.blockBlobWriter.WriteBlobAt(container, blob, offset, reader)
	nn -= zeroPadding
	return nn, err
}