package transformers

import (
	"os"

	"github.com/johnkerl/miller/v6/pkg/cli"
	"github.com/johnkerl/miller/v6/pkg/types"
)

// RecordTransformer is the interface satisfied by all transformers, i.e.,
// Miller verbs. See stream.go for context on the channels, as well as for
// context on end-of-record-stream signaling.
type RecordTransformer interface {
	Transform(
		inrecAndContext *types.RecordAndContext,
		outputRecordsAndContexts *[]*types.RecordAndContext, // list of *types.RecordAndContext
		inputDownstreamDoneChannel <-chan bool,
		outputDownstreamDoneChannel chan<- bool,
	)
}

type RecordTransformerFunc func(
	inrecAndContext *types.RecordAndContext,
	outputRecordsAndContexts *[]*types.RecordAndContext, // list of *types.RecordAndContext
	inputDownstreamDoneChannel <-chan bool,
	outputDownstreamDoneChannel chan<- bool,
)

// Used within some verbs
type RecordTransformerHelperFunc func(
	inrecAndContext *types.RecordAndContext,
	outputRecordsAndContexts *[]*types.RecordAndContext, // list of *types.RecordAndContext
)

type TransformerUsageFunc func(
	ostream *os.File,
)

// TransformerParseCLIFunc parses verb options from the CLI. Returns (nil, nil) on
// success for pass one (doConstruct=false). Returns (transformer, nil) on success
// for pass two (doConstruct=true). Returns (nil, cli.ErrHelpRequested) when -h/--help
// was used (caller should exit 0; usage already printed). Returns (nil, err) on
// parse or constructor failure (caller should print and exit 1).
type TransformerParseCLIFunc func(
	pargi *int,
	argc int,
	args []string,
	mainOptions *cli.TOptions,
	doConstruct bool, // false for first pass of CLI-parse, true for second pass
) (RecordTransformer, error)

type TransformerSetup struct {
	Verb         string
	UsageFunc    TransformerUsageFunc
	ParseCLIFunc TransformerParseCLIFunc

	// For seqgen only -- all other transformers process records sourced by the
	// record-reader.  The seqgen verb, by contrast, is a record-source of its
	// own. (The seqgen verb probably should have been designed as a zero-file
	// record "reader" object, rather than a verb, alas.)
	IgnoresInput bool
}

// HandleDefaultDownstreamDone is a utility function for most verbs other than
// head, tee, and seqgen to use for passing downstream-done flags back
// upstream.  See ChainTransformer for context.
func HandleDefaultDownstreamDone(
	inputDownstreamDoneChannel <-chan bool,
	outputDownstreamDoneChannel chan<- bool,
) {
	select {
	case b := <-inputDownstreamDoneChannel:
		outputDownstreamDoneChannel <- b
	default:
	}
}
