package ffs

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

	"github.com/pingcap/log"
)

// Implements Mounter
type ffsMounter struct {
	volumeName string
	volumePath string
	volumeArgs []string
	cmd        *exec.Cmd
}

const (
	ffsCmd = "ffs-client-linux"
)

func newArgs(volume, target string, volContext map[string]string) []string {
	args := []string{
		fmt.Sprintf("--%s=%s", argVolume, volume),
		fmt.Sprintf("--%s=%s", argTarget, target),
	}
	for k, v := range volContext {
		switch strings.ToLower(k) {
		case paramUniverse:
			args = append(args, fmt.Sprintf("--%s=%s", argUniverse, v))
		case paramZone:
			args = append(args, fmt.Sprintf("--%s=%s", argZone, v))
		case paramTenant:
			args = append(args, fmt.Sprintf("--%s=%s", argTenant, v))
		case paramKeepCache:
			args = append(args, fmt.Sprintf("--%s=%s", argKeepCache, v))
		case paramAsyncWrite:
			args = append(args, fmt.Sprintf("--%s=%s", argAsyncWrite, v))
		case paramMerge:
			args = append(args, fmt.Sprintf("--%s=%s", argMerge, v))
		case paramLogLevel:
			args = append(args, fmt.Sprintf("--%s=%s", argLogLevel, v))
		case paramUID:
			args = append(args, fmt.Sprintf("--%s=%s", argUID, v))
		case paramGID:
			args = append(args, fmt.Sprintf("--%s=%s", argGID, v))
		}
	}
	return args
}

func newRemoveArgs(universe, zone, tenant, name string) []string {
	args := []string{
		fmt.Sprintf("--%s=%s", argUniverse, universe),
		fmt.Sprintf("--%s=%s", argZone, zone),
		fmt.Sprintf("--%s=%s", argTenant, tenant),
		fmt.Sprintf("--%s=%s", argVolume, name),
		fmt.Sprintf("--%s", argRemove),
	}
	return args
}

func newFFSMounter(volumeName, volumePath string, volumeArgs []string) (*ffsMounter, error) {
	return &ffsMounter{
		volumeName: volumeName,
		volumePath: volumePath,
		volumeArgs: volumeArgs,
	}, nil
}

func (m *ffsMounter) Mount() error {
	log.S().Infof("mounting %s to %s", m.volumeName, m.volumePath)
	var err error
	m.cmd, err = fuseMount(m.volumePath, ffsCmd, m.volumeArgs)
	if err != nil {
		log.S().Errorf("mount to %s: %s", m.volumePath, err)
	}
	return err
}

func RemoveFFSVolume(universe, zone, tenant, name string) error {
	return removeVolume(ffsCmd, newRemoveArgs(universe, zone, tenant, name))
}
