package objectstore

import (
	"context"
	"io"
	"net/http"

	log "github.com/sirupsen/logrus"

	"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
)

// uploader is an io.WriteCloser that can be used as write end of the uploading pipe.
type uploader struct {
	// writeCloser is the writer bound to the request body
	io.WriteCloser

	// uploadError is the last error occourred during upload
	uploadError error
	// ctx is the internal context bound to the upload request
	ctx context.Context
}

func newUploader(ctx context.Context, w io.WriteCloser) uploader {
	return uploader{WriteCloser: w, ctx: ctx}
}

// Close implements the standard io.Closer interface: it closes the http client request.
// This method will also wait for the connection to terminate and return any error occurred during the upload
func (u *uploader) Close() error {
	if err := u.WriteCloser.Close(); err != nil {
		return err
	}

	<-u.ctx.Done()

	if err := u.ctx.Err(); err == context.DeadlineExceeded {
		return err
	}

	return u.uploadError
}

// syncAndDelete wait for Context to be Done and then performs the requested HTTP call
func (u *uploader) syncAndDelete(url string) {
	if url == "" {
		return
	}

	<-u.ctx.Done()

	req, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		log.WithError(err).WithField("object", helper.ScrubURLParams(url)).Warning("Delete failed")
		return
	}

	// here we are not using u.ctx because we must perform cleanup regardless of parent context
	resp, err := httpClient.Do(req)
	if err != nil {
		log.WithError(err).WithField("object", helper.ScrubURLParams(url)).Warning("Delete failed")
		return
	}
	resp.Body.Close()
}