<commit_before>package configurer

import (
	"fmt"

	"bufio"
	"os"

	"github.com/bpicode/fritzctl/fritz"
	"github.com/bpicode/fritzctl/meta"

	"encoding/json"

	"github.com/bpicode/fritzctl/stringutils"
	"golang.org/x/crypto/ssh/terminal"
)

// ExtendedConfig contains the fritz core config along with
// other data (like config file location).
type ExtendedConfig struct {
	fritzCfg fritz.Config
	file     string
}

// InteractiveCLI provides funtions to obtain user data from
// stdin and write the result to a file.
type InteractiveCLI interface {
	InitWithDefaultVaules(cfg ExtendedConfig)
	Obtain()
	Write() error
}

// CLI creates an InteractiveCLI instance.
func CLI() InteractiveCLI {
	return &interactiveCLI{}
}

// Defaults constructs an ExtendedConfig with default values.
func Defaults() ExtendedConfig {
	return ExtendedConfig{
		file: meta.DefaultConfigFileAbsolute(),
		fritzCfg: fritz.Config{
			Protocol: "https",
			Host:     "fritz.box",
			Password: "",
			LoginURL: "/login_sid.lua",
			Username: "",
		}}
}

type interactiveCLI struct {
	defaultValues ExtendedConfig
	userValues    ExtendedConfig
}

// InitWithDefaultVaules backs the interactiveCLI with default values that
// will be applied if the user does not want to change the field.
func (iCLI *interactiveCLI) InitWithDefaultVaules(cfg ExtendedConfig) {
	iCLI.defaultValues = cfg
	iCLI.userValues = iCLI.defaultValues
}

// Obtain starts the dialog session, asking for the values to fill
// an ExtendedConfig.
func (iCLI *interactiveCLI) Obtain() {
	scanner := bufio.NewScanner(os.Stdin)
	iCLI.userValues.file = next(fmt.Sprintf("Enter config file location [%s]: ",
		iCLI.defaultValues.file), scanner, iCLI.defaultValues.file)
	iCLI.userValues.fritzCfg.Protocol = next(fmt.Sprintf("Enter FRITZ!Box communication protocol [%s]: ",
		iCLI.defaultValues.fritzCfg.Protocol), scanner, iCLI.defaultValues.fritzCfg.Protocol)
	iCLI.userValues.fritzCfg.Host = next(fmt.Sprintf("Enter FRITZ!Box hostname/ip(:port) [%s]: ",
		iCLI.defaultValues.fritzCfg.Host), scanner, iCLI.defaultValues.fritzCfg.Host)
	iCLI.userValues.fritzCfg.LoginURL = next(fmt.Sprintf("Enter FRITZ!Box login path [%s]: ",
		iCLI.defaultValues.fritzCfg.LoginURL), scanner, iCLI.defaultValues.fritzCfg.LoginURL)
	iCLI.userValues.fritzCfg.Username = next(fmt.Sprintf("Enter FRITZ!Box username [%s]: ",
		iCLI.defaultValues.fritzCfg.Username), scanner, iCLI.defaultValues.fritzCfg.Username)
	iCLI.userValues.fritzCfg.Password = nextCredential("Enter FRITZ!Box password: ", iCLI.defaultValues.fritzCfg.Password)
}

// Write writes the user data to the configured file.
func (iCLI *interactiveCLI) Write() error {
	f, err := os.OpenFile(iCLI.userValues.file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()
	encoder := json.NewEncoder(f)
	encoder.SetIndent("", "  ")
	return encoder.Encode(&iCLI.userValues.fritzCfg)
}

func next(prompt string, scanner *bufio.Scanner, defaultValue string) string {
	fmt.Print(prompt)
	scanner.Scan()
	val := scanner.Text()
	return stringutils.DefaultIfEmpty(val, defaultValue)
}

func nextCredential(prompt string, defaultValue string) string {
	fmt.Print(prompt)
	pwBytes, _ := terminal.ReadPassword(0)
	return stringutils.DefaultIfEmpty(string(pwBytes), defaultValue)<commit_msg>remove call to setindent<commit_after>package configurer

import (
	"fmt"

	"bufio"
	"os"

	"github.com/bpicode/fritzctl/fritz"
	"github.com/bpicode/fritzctl/meta"

	"encoding/json"

	"github.com/bpicode/fritzctl/stringutils"
	"golang.org/x/crypto/ssh/terminal"
)

// ExtendedConfig contains the fritz core config along with
// other data (like config file location).
type ExtendedConfig struct {
	fritzCfg fritz.Config
	file     string
}

// InteractiveCLI provides funtions to obtain user data from
// stdin and write the result to a file.
type InteractiveCLI interface {
	InitWithDefaultVaules(cfg ExtendedConfig)
	Obtain()
	Write() error
}

// CLI creates an InteractiveCLI instance.
func CLI() InteractiveCLI {
	return &interactiveCLI{}
}

// Defaults constructs an ExtendedConfig with default values.
func Defaults() ExtendedConfig {
	return ExtendedConfig{
		file: meta.DefaultConfigFileAbsolute(),
		fritzCfg: fritz.Config{
			Protocol: "https",
			Host:     "fritz.box",
			Password: "",
			LoginURL: "/login_sid.lua",
			Username: "",
		}}
}

type interactiveCLI struct {
	defaultValues ExtendedConfig
	userValues    ExtendedConfig
}

// InitWithDefaultVaules backs the interactiveCLI with default values that
// will be applied if the user does not want to change the field.
func (iCLI *interactiveCLI) InitWithDefaultVaules(cfg ExtendedConfig) {
	iCLI.defaultValues = cfg
	iCLI.userValues = iCLI.defaultValues
}

// Obtain starts the dialog session, asking for the values to fill
// an ExtendedConfig.
func (iCLI *interactiveCLI) Obtain() {
	scanner := bufio.NewScanner(os.Stdin)
	iCLI.userValues.file = next(fmt.Sprintf("Enter config file location [%s]: ",
		iCLI.defaultValues.file), scanner, iCLI.defaultValues.file)
	iCLI.userValues.fritzCfg.Protocol = next(fmt.Sprintf("Enter FRITZ!Box communication protocol [%s]: ",
		iCLI.defaultValues.fritzCfg.Protocol), scanner, iCLI.defaultValues.fritzCfg.Protocol)
	iCLI.userValues.fritzCfg.Host = next(fmt.Sprintf("Enter FRITZ!Box hostname/ip(:port) [%s]: ",
		iCLI.defaultValues.fritzCfg.Host), scanner, iCLI.defaultValues.fritzCfg.Host)
	iCLI.userValues.fritzCfg.LoginURL = next(fmt.Sprintf("Enter FRITZ!Box login path [%s]: ",
		iCLI.defaultValues.fritzCfg.LoginURL), scanner, iCLI.defaultValues.fritzCfg.LoginURL)
	iCLI.userValues.fritzCfg.Username = next(fmt.Sprintf("Enter FRITZ!Box username [%s]: ",
		iCLI.defaultValues.fritzCfg.Username), scanner, iCLI.defaultValues.fritzCfg.Username)
	iCLI.userValues.fritzCfg.Password = nextCredential("Enter FRITZ!Box password: ", iCLI.defaultValues.fritzCfg.Password)
}

// Write writes the user data to the configured file.
func (iCLI *interactiveCLI) Write() error {
	f, err := os.OpenFile(iCLI.userValues.file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()
	return json.NewEncoder(f).Encode(&iCLI.userValues.fritzCfg)
}

func next(prompt string, scanner *bufio.Scanner, defaultValue string) string {
	fmt.Print(prompt)
	scanner.Scan()
	val := scanner.Text()
	return stringutils.DefaultIfEmpty(val, defaultValue)
}

func nextCredential(prompt string, defaultValue string) string {
	fmt.Print(prompt)
	pwBytes, _ := terminal.ReadPassword(0)
	return stringutils.DefaultIfEmpty(string(pwBytes), defaultValue)
{'fraction_non_alphanumeric': 0.11538461538461539, 'fraction_numerical': 0.0015262515262515263, 'mean_word_length': 5.067592592592592, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '627906', 'n_tokens_mistral': 2320, 'n_tokens_neox': 2193, 'n_words': 503}