// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package versioner

import (
	"errors"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/syncthing/syncthing/lib/osutil"
)

func init() {
	// Register the constructor for this type of versioner with the name "external"
	Factories["external"] = NewExternal
}

type External struct {
	command    string
	folderPath string
}

func NewExternal(folderID, folderPath string, params map[string]string) Versioner {
	command := params["command"]

	s := External{
		command:    command,
		folderPath: folderPath,
	}

	l.Debugf("instantiated %#v", s)
	return s
}

// Archive moves the named file away to a version archive. If this function
// returns nil, the named file does not exist any more (has been archived).
func (v External) Archive(filePath string) error {
	_, err := osutil.Lstat(filePath)
	if os.IsNotExist(err) {
		l.Debugln("not archiving nonexistent file", filePath)
		return nil
	} else if err != nil {
		return err
	}

	l.Debugln("archiving", filePath)

	inFolderPath, err := filepath.Rel(v.folderPath, filePath)
	if err != nil {
		return err
	}

	if v.command == "" {
		return errors.New("Versioner: command is empty, please enter a valid command")
	}

	cmd := exec.Command(v.command, v.folderPath, inFolderPath)
	env := os.Environ()
	// filter STGUIAUTH and STGUIAPIKEY from environment variables
	filteredEnv := []string{}
	for _, x := range env {
		if !strings.HasPrefix(x, "STGUIAUTH=") && !strings.HasPrefix(x, "STGUIAPIKEY=") {
			filteredEnv = append(filteredEnv, x)
		}
	}
	cmd.Env = filteredEnv
	err = cmd.Run()
	if err != nil {
		return err
	}

	// return error if the file was not removed
	if _, err = osutil.Lstat(filePath); os.IsNotExist(err) {
		return nil
	}
	return errors.New("Versioner: file was not removed by external script")
}
