package main

import (
	"context"
	"fmt"
	"os"
	"strings"

	_ "github.com/lib/pq"
	_ "modernc.org/sqlite"
	"github.com/oklog/ulid/v2"

	"go.sour.is/passwd"
	"go.sour.is/passwd/pkg/argon2"
	"go.sour.is/pkg/lg"
	"go.sour.is/pkg/mercury/app"
	"go.sour.is/pkg/mercury/http"
	"go.sour.is/pkg/ident"
	"go.sour.is/pkg/ident/source"
	"go.sour.is/pkg/mercury/mqtt"
	"go.sour.is/pkg/mercury/sql"
	"go.sour.is/pkg/service"
	"go.sour.is/pkg/xdg"

	"go.sour.is/pkg/mercury"
)

var baseConfig = `
# mercury.source [handler] [name]
#@mercury.source.http-notify.default

@mercury.source.http-notify.default
match    :1 d42.*
endpoint :http://example.com/webhook

@mercury.source.mqtt-notify.default
#match    :0 *
#endpoint :mqtt://example.com/topic
disabled :

@mercury.source.mercury-default.default
match :1 mercury.*

@mercury.source.mercury-environ.environ
match :1 mercury.*
`

var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error {
	ctx, span := lg.Span(ctx)
	defer span.End()

	conf, err := readConfig(ctx)
	if err != nil {
		return err
	}

	app.Register("local", conf)
	http.Register()
	mqtt.Register()
	sql.Register()

	err = mercury.Registry.Configure(conf)
	if err != nil {
		return err
	}

	span.AddEvent("Enable Mercury")
	idm := ident.NewIDM(passwd.New(argon2.Argon2id), ulid.DefaultEntropy())

	idm.Add(1, source.NewMercury(mercury.Registry, idm))
	svc.Add(mercury.NewHTTP(), ident.NewHTTP(idm))

	return nil
})

func readConfig(ctx context.Context) (mercury.SpaceMap, error) {
	_, span := lg.Span(ctx)
	defer span.End()

	conf, err := mercury.ParseText(strings.NewReader(baseConfig))
	if err != nil {
		return nil, err
	}

	wd, err := os.Getwd()
	if err != err {
		return nil, err
	}

	for _, fn := range xdg.Find(wd+":"+xdg.EnvConfigDirs, "config.mercury") {
		span.AddEvent(fmt.Sprint("config:", fn))

		fd, err := os.Open(fn)
		if err != nil {
			return nil, err
		}
		defer fd.Close()

		c, err := mercury.ParseText(fd)
		if err != nil {
			return nil, err
		}
		conf.MergeMap(c)
	}

	return conf, nil
}
