package backend

import (
	"fmt"
	"io"
	"strings"

	"github.com/aws/aws-sdk-go/aws/session"

	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3iface"
)

const backendS3 = "s3"

type S3Backend struct {
	input    s3.GetObjectInput
	reader   io.ReadCloser
	S3Client s3iface.S3API
}

func NewS3Reader(path string) (*S3Backend, error) {

	backend := S3Backend{}
	bucketPath := strings.Split(path, "/")
	if len(bucketPath) < 2 {
		return nil, fmt.Errorf("Unable to parse S3 path: %s. Must be BUCKET_NAME/PATH/TO/OBJECT", path)
	}
	bucket := bucketPath[0]
	key := strings.Join(bucketPath[1:], "/")

	backend.input = s3.GetObjectInput{
		Key:    &key,
		Bucket: &bucket,
	}
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		SharedConfigState: session.SharedConfigEnable,
	}))
	backend.S3Client = s3.New(sess)
	return &backend, nil
}

func (s *S3Backend) Read(p []byte) (n int, err error) {
	if s.reader == nil {
		response, err := s.S3Client.GetObject(&s.input)
		if err != nil {
			requestFailure, ok := err.(s3.RequestFailure)
			if ok {
				return 0, fmt.Errorf("Error reading state '%s' from s3 bucket '%s': %s", *s.input.Key, *s.input.Bucket, requestFailure.Message())
			}
			return 0, err
		}
		s.reader = response.Body
	}
	return s.reader.Read(p)
}

func (s *S3Backend) Close() error {
	if s.reader != nil {
		return s.reader.Close()
	}
	return fmt.Errorf("Unable to close reader as nothing was opened")
}
