// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT

package filesystem

import (
	"context"
	"io"
	"os"
	"path/filepath"

	"code.forgejo.org/f3/gof3/v3/f3"
	"code.forgejo.org/f3/gof3/v3/id"
	"code.forgejo.org/f3/gof3/v3/tree/generic"
)

type attachmentDriver struct {
	nodeDriver
}

func newAttachmentDriver(content f3.Interface) generic.NodeDriverInterface {
	n := newNodeDriver(content).(*nodeDriver)
	a := &attachmentDriver{
		nodeDriver: *n,
	}
	return a
}

func (o *attachmentDriver) getPath() string {
	f := o.content.(*f3.Attachment)
	options := o.GetTreeDriver().(*treeDriver).options
	return filepath.Join(options.Directory, "objects", f.SHA256[0:2], f.SHA256[2:4], f.SHA256)
}

func (o *attachmentDriver) save(ctx context.Context) {
	attachmentFormat := o.content.(*f3.Attachment)
	objectsHelper := o.getF3Tree().GetObjectsHelper()
	sha, tmpPath := objectsHelper.Save(attachmentFormat.DownloadFunc())
	attachmentFormat.SHA256 = sha
	path := o.getPath()
	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
		panic(err)
	}
	if err := os.Rename(tmpPath, path); err != nil {
		panic(err)
	}
	o.GetNode().Trace("%s %s", attachmentFormat.SHA256, path)
}

func (o *attachmentDriver) setDownloadFunc() {
	f := o.content.(*f3.Attachment)
	f.DownloadFunc = func() io.ReadCloser {
		f, err := os.Open(o.getPath())
		if err != nil {
			panic(err)
		}
		return f
	}
}

func (o *attachmentDriver) Put(ctx context.Context) id.NodeID {
	return o.upsert(ctx)
}

func (o *attachmentDriver) Patch(ctx context.Context) {
	o.upsert(ctx)
}

func (o *attachmentDriver) upsert(ctx context.Context) id.NodeID {
	attachmentFormat := o.content.(*f3.Attachment)
	if attachmentFormat.SHA256 != "" {
		o.save(ctx)
	}
	o.setDownloadFunc()
	return o.nodeDriver.upsert(ctx)
}

func (o *attachmentDriver) Get(ctx context.Context) bool {
	if o.nodeDriver.Get(ctx) {
		o.setDownloadFunc()
		return true
	}
	return false
}
