// This file is part of tdir, the Taler Directory implementation.
// Copyright (C) 2025 Martin Schanzenbach
//
// Taldir is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// Taldir is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: AGPL3.0-or-later

package taldir

import (
	"fmt"
	"os/exec"
	"strings"
)

type GnsDisseminator struct {
	// Config
	config *TaldirConfig
}

func (d *GnsDisseminator) gnsCheckIsDisseminated(e *Entry) bool {
	path, err := exec.LookPath("gnunet-gns")
	if err != nil {
		return false
	}
	zone := d.config.Ini.GetString("directory-disseminator-gns", "zone", "taldir")
	out, err := exec.Command(path, "--lookup", e.HsAlias+"."+zone, "--type", "TXT").Output()
	if err != nil {
		return false
	}
	return strings.Contains(string(out), "TXT: `"+e.TargetURI+"'")
}

func (d *GnsDisseminator) DisseminateStop(e *Entry) error {
	if !d.gnsCheckIsDisseminated(e) {
		return nil
	}
	path, err := exec.LookPath("gnunet-namestore")
	if err != nil {
		return fmt.Errorf("path of command not found: %w", err)
	}
	zone := d.config.Ini.GetString("directory-disseminator-gns", "zone", "taldir")
	out, err := exec.Command(path, "--delete", "--public", "--zone", zone, "--type", "TXT", "--name", e.HsAlias, "--value", e.TargetURI).Output()
	if err != nil {
		return fmt.Errorf("failed to execute disseminator command: `%s', %w", out, err)
	}
	return nil
}

func (d *GnsDisseminator) DisseminateStart(e *Entry) error {
	if d.gnsCheckIsDisseminated(e) {
		fmt.Printf("`%s' is already being disseminated\n", e.HsAlias)
		return nil
	}
	path, err := exec.LookPath("gnunet-namestore")
	if err != nil {
		return fmt.Errorf("path of command not found: %w", err)
	}
	expiration := d.config.Ini.GetString("directory-disseminator-gns", "expiration", "1d")
	zone := d.config.Ini.GetString("directory-disseminator-gns", "zone", "taldir")
	out, err := exec.Command(path, "--add", "--public", "--expiration", expiration, "--zone", zone, "--type", "TXT", "--name", e.HsAlias, "--value", e.TargetURI).Output()
	if err != nil {
		return fmt.Errorf("failed to execute disseminator command: `%s', %w", out, err)
	}
	return nil
}

func (d *GnsDisseminator) Name() string {
	return "gns"
}

func (d *GnsDisseminator) IsEnabled() bool {
	return d.config.Ini.GetBool("directory-disseminator-gns", "enabled", false)
}

func makeGnsDisseminator(cfg *TaldirConfig) GnsDisseminator {
	d := GnsDisseminator{
		config: cfg,
	}
	return d
}
