// Code generated by go-swagger; DO NOT EDIT.

package cli

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"fmt"
	"log"
	"os"
	"path"
	"path/filepath"

	"github.com/go-openapi/runtime"
	httptransport "github.com/go-openapi/runtime/client"
	"github.com/go-openapi/strfmt"
	"github.com/go-swagger/go-swagger/examples/cli/client"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var (
	// debug flag indicating that cli should output debug logs
	debug bool

	// config file location
	configFile string

	// dry run flag
	dryRun bool

	// name of the executable
	exeName = filepath.Base(os.Args[0])
)

// logDebugf writes debug log to stdout
func logDebugf(format string, v ...interface{}) {
	if !debug {
		return
	}
	log.Printf(format, v...)
}

// depth of recursion to construct model flags
var maxDepth int = 5

// makeClient constructs a client object
func makeClient(cmd *cobra.Command, _ []string) (*client.AToDoListApplication, error) {
	hostname := viper.GetString("hostname")
	viper.SetDefault("base_path", client.DefaultBasePath)
	basePath := viper.GetString("base_path")
	scheme := viper.GetString("scheme")

	r := httptransport.New(hostname, basePath, []string{scheme})
	r.SetDebug(debug)
	// set custom producer and consumer to use the default ones

	r.Consumers["application/io.goswagger.examples.todo-list.v1+json"] = runtime.JSONConsumer()

	r.Producers["application/io.goswagger.examples.todo-list.v1+json"] = runtime.JSONProducer()

	auth, err := makeAuthInfoWriter(cmd)
	if err != nil {
		return nil, err
	}
	r.DefaultAuthentication = auth

	appCli := client.New(r, strfmt.Default)
	logDebugf("Server url: %v://%v", scheme, hostname)

	return appCli, nil
}

// MakeRootCmd returns the root cmd
func MakeRootCmd() (*cobra.Command, error) {
	cobra.OnInitialize(initViperConfigs)

	// Use executable name as the command name
	rootCmd := &cobra.Command{
		Use: exeName,
	}

	// register basic flags
	rootCmd.PersistentFlags().String("hostname", client.DefaultHost, "hostname of the service")
	if err := viper.BindPFlag("hostname", rootCmd.PersistentFlags().Lookup("hostname")); err != nil {
		return nil, err
	}
	rootCmd.PersistentFlags().String("scheme", client.DefaultSchemes[0], fmt.Sprintf("Choose from: %v", client.DefaultSchemes))
	if err := viper.BindPFlag("scheme", rootCmd.PersistentFlags().Lookup("scheme")); err != nil {
		return nil, err
	}
	rootCmd.PersistentFlags().String("base-path", client.DefaultBasePath, fmt.Sprintf("For example: %v", client.DefaultBasePath))
	if err := viper.BindPFlag("base_path", rootCmd.PersistentFlags().Lookup("base-path")); err != nil {
		return nil, err
	}

	// configure debug flag
	rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "output debug logs")
	// configure config location
	rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file path")
	// configure dry run flag
	rootCmd.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "do not send the request to server")

	// register security flags
	if err := registerAuthInoWriterFlags(rootCmd); err != nil {
		return nil, err
	}

	// add all operation groups
	c0, err := makeGroupOfOperationsOperationsCmd()
	if err != nil {
		return nil, err
	}
	rootCmd.AddCommand(c0)
	c1, err := makeGroupOfOperationsTodosCmd()
	if err != nil {
		return nil, err
	}
	rootCmd.AddCommand(c1)

	// add cobra completion
	rootCmd.AddCommand(makeGenCompletionCmd())

	return rootCmd, nil
}

// initViperConfigs initialize viper config using config file in '$HOME/.config/<cli name>/config.<json|yaml...>'
// currently hostname, scheme and auth tokens can be specified in this config file.
func initViperConfigs() {
	if configFile != "" {
		// use user specified config file location
		viper.SetConfigFile(configFile)
	} else {
		var (
			configDir string
			err       error
		)

		// look for default config (OS-specific, e.g. ".config" on linux)
		configDir, err = os.UserConfigDir()
		if err != nil {
			// fallback and try finding the home directory.
			home, err := os.UserHomeDir()
			cobra.CheckErr(err)
			configDir = path.Join(home, ".config")
		}

		// Search config in the config directory with name of the CLI binary (without extension).
		configDir = path.Join(configDir, exeName)
		viper.AddConfigPath(configDir)
		viper.SetConfigName("config")
	}

	if err := viper.ReadInConfig(); err != nil {
		logDebugf("Error: loading config file: %v", err)
		return
	}
	logDebugf("Using config file: %v", viper.ConfigFileUsed())
}

// registerAuthInoWriterFlags registers all flags needed to perform authentication
func registerAuthInoWriterFlags(cmd *cobra.Command) error {
	// x-todolist-token
	cmd.PersistentFlags().String("x-todolist-token", "", ``)
	if err := viper.BindPFlag("x-todolist-token", cmd.PersistentFlags().Lookup("x-todolist-token")); err != nil {
		return err
	}

	return nil
}

// makeAuthInfoWriter retrieves cmd flags and construct an auth info writer
func makeAuthInfoWriter(cmd *cobra.Command) (runtime.ClientAuthInfoWriter, error) {
	auths := []runtime.ClientAuthInfoWriter{}

	// x-todolist-token
	if viper.IsSet("x-todolist-token") {
		XTodolistTokenKey := viper.GetString("x-todolist-token")
		auths = append(auths, httptransport.APIKeyAuth("x-todolist-token", "header", XTodolistTokenKey))
	}

	if len(auths) == 0 {
		logDebugf("Warning: No auth params detected.")
		return nil, nil
	}

	// compose all auths together
	return httptransport.Compose(auths...), nil
} // makeGroupOfOperationsOperationsCmd returns a parent command to handle all operations with tag "operations"
func makeGroupOfOperationsOperationsCmd() (*cobra.Command, error) {
	parent := &cobra.Command{
		Use:  "operations",
		Long: ``,
	}

	sub0, err := makeOperationOperationsPutTest2766Cmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub0)

	return parent, nil
} // makeGroupOfOperationsTodosCmd returns a parent command to handle all operations with tag "todos"
func makeGroupOfOperationsTodosCmd() (*cobra.Command, error) {
	parent := &cobra.Command{
		Use:  "todos",
		Long: ``,
	}

	sub0, err := makeOperationTodosAddOneCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub0)

	sub1, err := makeOperationTodosDestroyOneCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub1)

	sub2, err := makeOperationTodosFindTodosCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub2)

	sub3, err := makeOperationTodosUpdateOneCmd()
	if err != nil {
		return nil, err
	}
	parent.AddCommand(sub3)

	return parent, nil
}
