// Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.

package {{(.TrimPrefix "account").SnakeName}}

import (
    "github.com/databricks/cli/libs/cmdio"
    "github.com/databricks/cli/libs/flags"
	"github.com/databricks/cli/cmd/root"
	"github.com/databricks/databricks-sdk-go/service/{{.Package.Name}}"
	"github.com/spf13/cobra"
)

{{ $excludes :=
	list
		"command-execution"
		"statement-execution"
		"dbfs"
		"dbsql-permissions"
		"account-access-control-proxy"
		"files"
}}

{{if not (in $excludes .KebabName) }}
	{{template "service" .}}
{{else}}
	{{skipThisFile}}
{{end}}

{{define "printArray" -}}
{{if le (len .) 5 -}}
	[{{range $index, $element := .}}{{if ne $index 0}}, {{end}}{{$element.Name}}{{end}}]
{{- else -}}[{{range $index, $element := .}}
  {{$element.Name}},{{end}}
]{{end}}{{end}}

{{define "service"}}
// Slice with functions to override default command behavior.
// Functions can be added from the `init()` function in manually curated files in this directory.
var cmdOverrides []func(*cobra.Command)

func New() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "{{(.TrimPrefix "account").KebabName}}",
		{{- if .Description }}
		Short: `{{.Summary | without "`"}}`,
		Long: `{{.Comment  "  " 80 | without "`"}}`,
		{{- end }}
		GroupID: "{{ .Package.Name }}",
		Annotations: map[string]string{
			"package": "{{ .Package.Name }}",
		},
		{{- if .IsPrivatePreview }}

		// This service is being previewed; hide from help output.
		Hidden: true,
		{{- end }}
	}

	// Apply optional overrides to this command.
	for _, fn := range cmdOverrides {
		fn(cmd)
	}

	return cmd
}

{{- $serviceName := .KebabName -}}
{{range .Methods}}

{{- $excludes := list "put-secret" -}}
{{if in $excludes .KebabName }}
	{{continue}}
{{end}}
// start {{.KebabName}} command

// Slice with functions to override default command behavior.
// Functions can be added from the `init()` function in manually curated files in this directory.
var {{.CamelName}}Overrides []func(
	*cobra.Command,
	{{- if .Request }}
	*{{.Service.Package.Name}}.{{.Request.PascalName}},
	{{- end }}
)

func new{{.PascalName}}() *cobra.Command {
	cmd := &cobra.Command{}

	{{- if .Request}}

	var {{.CamelName}}Req {{.Service.Package.Name}}.{{.Request.PascalName}}
	{{- if .CanUseJson}}
	var {{.CamelName}}Json flags.JsonFlag
	{{- end}}
	{{- end}}

	{{if .Wait}}var {{.CamelName}}SkipWait bool
	var {{.CamelName}}Timeout time.Duration{{end}}

	{{if .Wait}}
	cmd.Flags().BoolVar(&{{.CamelName}}SkipWait, "no-wait", {{.CamelName}}SkipWait, `do not wait to reach {{range $i, $e := .Wait.Success}}{{if $i}} or {{end}}{{.Content}}{{end}} state`)
	cmd.Flags().DurationVar(&{{.CamelName}}Timeout, "timeout", {{.Wait.Timeout}}*time.Minute, `maximum amount of time to reach {{range $i, $e := .Wait.Success}}{{if $i}} or {{end}}{{.Content}}{{end}} state`)
	{{end -}}
    {{if .Request}}// TODO: short flags
	{{- if .CanUseJson}}
	cmd.Flags().Var(&{{.CamelName}}Json, "json", `either inline JSON string or @path/to/file.json with request body`)
	{{- end}}
    {{$method := .}}
	{{ if not .IsJsonOnly }}
	{{range .Request.Fields -}}
		{{- if not .Required -}}
			{{if .Entity.IsObject }}// TODO: complex arg: {{.Name}}
			{{else if .Entity.IsAny }}// TODO: any: {{.Name}}
			{{else if .Entity.ArrayValue }}// TODO: array: {{.Name}}
			{{else if .Entity.MapValue }}// TODO: map via StringToStringVar: {{.Name}}
			{{else if .Entity.IsEmpty }}// TODO: output-only field
			{{else if .Entity.Enum }}cmd.Flags().Var(&{{$method.CamelName}}Req.{{.PascalName}}, "{{.KebabName}}", `{{.Summary | without "`" | trimSuffix "."}}. Supported values: {{template "printArray" .Entity.Enum}}`)
			{{else}}cmd.Flags().{{template "arg-type" .Entity}}(&{{$method.CamelName}}Req.{{.PascalName}}, "{{.KebabName}}", {{$method.CamelName}}Req.{{.PascalName}}, `{{.Summary | without "`"}}`)
			{{end}}
		{{- end -}}
	{{- end}}
	{{- end}}
	{{end}}

	{{- $excludeFromPrompts := list "workspace get-status" -}}
	{{- $fullCommandName := (print $serviceName " " .KebabName) -}}
	{{- $noPrompt := or .IsCrudCreate (in $excludeFromPrompts $fullCommandName) }}

	{{- $hasPosArgs := .HasRequiredPositionalArguments -}}
	{{- $hasSinglePosArg := and $hasPosArgs (eq 1 (len .Request.RequiredFields)) -}}
	{{- $serviceHasNamedIdMap := and (and .Service.List .Service.List.NamedIdMap) (not (eq .PascalName "List")) -}}
	{{- $hasIdPrompt := and (not $noPrompt) (and $hasSinglePosArg $serviceHasNamedIdMap) -}}
	{{- $wait := and .Wait (and (not .IsCrudRead) (not (eq .SnakeName "get_run"))) -}}
	{{- $hasRequiredArgs :=  and (not $hasIdPrompt) $hasPosArgs -}}
	{{- $hasSingleRequiredRequestBodyFieldWithPrompt := and (and $hasIdPrompt .Request) (eq 1 (len .Request.RequiredRequestBodyFields))  -}}
	{{- $onlyPathArgsRequiredAsPositionalArguments := and .Request (eq (len .RequiredPositionalArguments) (len .Request.RequiredPathFields)) -}}
	{{- $hasDifferentArgsWithJsonFlag := and (not $onlyPathArgsRequiredAsPositionalArguments) (and .CanUseJson .Request.HasRequiredRequestBodyFields) -}}
	{{- $hasCustomArgHandler := or $hasRequiredArgs $hasDifferentArgsWithJsonFlag -}}

	{{- $atleastOneArgumentWithDescription := false -}}
	{{- if $hasPosArgs -}}
		{{- range .RequiredPositionalArguments -}}
			{{- if .HasComment -}}
				{{- $atleastOneArgumentWithDescription = true -}}
				{{- break -}}
			{{- end -}}
		{{- end -}}
	{{- end -}}

	cmd.Use = "{{.KebabName}}{{if $hasPosArgs}}{{range .RequiredPositionalArguments}} {{.ConstantName}}{{end}}{{end}}"
	{{- if .Description }}
	cmd.Short = `{{.Summary | without "`"}}`
	cmd.Long = `{{.Comment  "  " 80 | without "`"}}
	{{- if $atleastOneArgumentWithDescription }}

  Arguments:
    {{- range .RequiredPositionalArguments }}
    {{ .ConstantName }}: {{.Comment "      " 80 | without "`"}}
    {{- end -}}
    {{- end -}}
	`
	{{- end }}
	{{- if .IsPrivatePreview }}

	// This command is being previewed; hide from help output.
	cmd.Hidden = true
	{{- end }}

	cmd.Annotations = make(map[string]string)
	{{ if $hasCustomArgHandler }}
	cmd.Args = func(cmd *cobra.Command, args []string) error {
		{{- if $hasDifferentArgsWithJsonFlag }}
		if cmd.Flags().Changed("json") {
			err := cobra.ExactArgs({{len .Request.RequiredPathFields}})(cmd, args)
			if err != nil {
			{{- if eq 0 (len .Request.RequiredPathFields) }}
				return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide{{- range $index, $field := .Request.RequiredFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input")
			{{- else }}
				return fmt.Errorf("when --json flag is specified, provide only{{- range $index, $field := .Request.RequiredPathFields}}{{if $index}},{{end}} {{$field.ConstantName}}{{end}} as positional arguments. Provide{{- range $index, $field := .Request.RequiredRequestBodyFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input")
			{{- end }}
			}
			return nil
		}
		{{- end }}
		{{- if $hasRequiredArgs }}
		check := cobra.ExactArgs({{len .RequiredPositionalArguments}})
		return check(cmd, args)
		{{- else}}
		return nil
		{{- end }}
	}
	{{ end }}
	cmd.PreRunE = root.Must{{if .Service.IsAccounts}}Account{{else}}Workspace{{end}}Client
	cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
		ctx := cmd.Context()
		{{if .Service.IsAccounts}}a := root.AccountClient(ctx){{else}}w := root.WorkspaceClient(ctx){{end}}
		{{- if .Request }}
			{{ if .CanUseJson }}
			if cmd.Flags().Changed("json") {
					err = {{.CamelName}}Json.Unmarshal(&{{.CamelName}}Req)
					if err != nil {
						return err
					}
			}{{end}}{{ if .MustUseJson }}else {
				return fmt.Errorf("please provide command input in JSON format by specifying the --json flag")
			}{{- end}}
			{{- if $hasPosArgs }}
			{{- if and .CanUseJson $hasSingleRequiredRequestBodyFieldWithPrompt }} else {
			{{- end}}
			{{- if $hasIdPrompt}}
				if len(args) == 0 {
					promptSpinner := cmdio.Spinner(ctx)
					promptSpinner <- "No{{range .Request.RequiredFields}} {{.ConstantName}}{{end}} argument specified. Loading names for {{.Service.TitleName}} drop-down."
					names, err := {{if .Service.IsAccounts}}a{{else}}w{{end}}.{{(.Service.TrimPrefix "account").PascalName}}.{{.Service.List.NamedIdMap.PascalName}}(ctx{{if .Service.List.Request}}, {{.Service.Package.Name}}.{{.Service.List.Request.PascalName}}{}{{end}})
					close(promptSpinner)
					if err != nil {
						return fmt.Errorf("failed to load names for {{.Service.TitleName}} drop-down. Please manually specify required arguments. Original error: %w", err)
					}
					id, err := cmdio.Select(ctx, names, "{{range .Request.RequiredFields}}{{.Summary | trimSuffix "."}}{{end}}")
					if err != nil {
						return err
					}
					args = append(args, id)
				}
				if len(args) != 1 {
					return fmt.Errorf("expected to have {{range .Request.RequiredFields}}{{.Summary | trimSuffix "." | lower}}{{end}}")
				}
			{{- end -}}

			{{$method := .}}
			{{- range $arg, $field := .RequiredPositionalArguments}}
				{{- template "args-scan" (dict "Arg" $arg "Field" $field "Method" $method "HasIdPrompt" $hasIdPrompt)}}
			{{- end -}}
			{{- if and .CanUseJson $hasSingleRequiredRequestBodyFieldWithPrompt }}
			}
			{{- end}}

			{{- end}}
		{{end}}
		{{if $wait -}}
		wait, err := {{if .Service.IsAccounts}}a{{else}}w{{end}}.{{.Service.PascalName}}.{{.PascalName}}(ctx{{if .Request}}, {{.CamelName}}Req{{end}})
		if err != nil {
			return err
		}
		if {{.CamelName}}SkipWait {
			{{if .Response -}}
			return cmdio.Render(ctx, wait.Response)
			{{- else -}}
			return nil
			{{- end}}
		}
		spinner := cmdio.Spinner(ctx)
		info, err := wait.OnProgress(func(i *{{.Service.Package.Name}}.{{.Wait.Poll.Response.PascalName}}) {
			{{if .Wait.MessagePath -}}
			{{if .Wait.ComplexMessagePath -}}
			if i.{{.Wait.MessagePathHead.PascalName}} == nil {
				return
			}
			status := i{{range .Wait.StatusPath}}.{{.PascalName}}{{end}}
			statusMessage := fmt.Sprintf("current status: %s", status)
			if i.{{.Wait.MessagePathHead.PascalName}} != nil {
				statusMessage = i{{range .Wait.MessagePath}}.{{.PascalName}}{{end}}
			}
			{{- else -}}
			statusMessage := i{{range .Wait.MessagePath}}.{{.PascalName}}{{end}}
			{{- end}}
			{{- else -}}
			status := i{{range .Wait.StatusPath}}.{{.PascalName}}{{end}}
			statusMessage := fmt.Sprintf("current status: %s", status)
			{{- end}}
			spinner <- statusMessage
		}).GetWithTimeout({{.CamelName}}Timeout)
		close(spinner)
		if err != nil {
			return err
		}
		return cmdio.Render(ctx, info)
		{{- else -}}
		{{template "method-call" .}}
		{{end -}}
	}

	// Disable completions since they are not applicable.
	// Can be overridden by manual implementation in `override.go`.
	cmd.ValidArgsFunction = cobra.NoFileCompletions

	// Apply optional overrides to this command.
	for _, fn := range {{.CamelName}}Overrides {
		fn(cmd{{if .Request}}, &{{.CamelName}}Req{{end}})
	}

	return cmd
}

func init() {
	cmdOverrides = append(cmdOverrides, func(cmd *cobra.Command) {
		cmd.AddCommand(new{{.PascalName}}())
	})
}
{{end}}
// end service {{.Name}}{{end}}

{{- define "method-call" -}}
		{{if .Response}}response, err :={{else}}err ={{end}} {{if .Service.IsAccounts}}a{{else}}w{{end}}.{{(.Service.TrimPrefix "account").PascalName}}.{{.PascalName}}{{if .Pagination}}All{{end}}(ctx{{if .Request}}, {{.CamelName}}Req{{end}})
		if err != nil {
			return err
		}
		{{ if .Response -}}
			{{- if .IsResponseByteStream -}}
			defer response.{{.ResponseBodyField.PascalName}}.Close()
			return cmdio.RenderReader(ctx, response.{{.ResponseBodyField.PascalName}})
			{{- else -}}
			return cmdio.Render(ctx, response)
			{{- end -}}
		{{ else -}}
		return nil
		{{- end -}}
{{- end -}}

{{- define "arg-type" -}}
	{{- if .IsString}}StringVar
	{{- else if .IsBool}}BoolVar
	{{- else if .IsInt64}}Int64Var
	{{- else if .IsFloat64}}Float64Var
	{{- else if .IsInt}}IntVar
	{{- else if .Enum }}StringVar
	{{- else}}/* NOT PRIMITIVE */
	{{- end -}}
{{- end -}}

{{- define "args-scan" -}}
	{{- $field := .Field -}}
	{{- $method := .Method -}}
	{{- $arg := .Arg -}}
	{{- $hasIdPrompt := .HasIdPrompt -}}
	{{- $optionalIfJsonIsUsed := and (not $hasIdPrompt) (and $field.IsRequestBodyField $method.CanUseJson) }}
	{{- if $optionalIfJsonIsUsed  }}
	if !cmd.Flags().Changed("json") {
	{{- end }}
	{{if not $field.Entity.IsString -}}
	_, err = fmt.Sscan(args[{{$arg}}], &{{$method.CamelName}}Req.{{$field.PascalName}})
	if err != nil {
		return fmt.Errorf("invalid {{$field.ConstantName}}: %s", args[{{$arg}}])
	}{{else -}}
	{{$method.CamelName}}Req.{{$field.PascalName}} = args[{{$arg}}]
	{{- end -}}
	{{- if $optionalIfJsonIsUsed  }}
	}
	{{- end }}
{{- end -}}
