// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tool

import (
	"io"
	"os"

	"v.io/jiri/gerrit"
	"v.io/jiri/gitutil"
	"v.io/jiri/jenkins"
	"v.io/jiri/runutil"
	"v.io/x/lib/cmdline"
	"v.io/x/lib/envvar"
	"v.io/x/lib/timing"
)

// Context represents an execution context of a tool command
// invocation. Its purpose is to enable sharing of state throughout
// the lifetime of a command invocation.
type Context struct {
	opts  ContextOpts
	run   *runutil.Run
	seq   *runutil.Sequence
	start *runutil.Start
}

// ContextOpts records the context options.
type ContextOpts struct {
	Color    *bool
	DryRun   *bool
	Env      map[string]string
	Manifest *string
	Stdin    io.Reader
	Stdout   io.Writer
	Stderr   io.Writer
	Verbose  *bool
	Timer    *timing.Timer
}

// newContextOpts is the ContextOpts factory.
func newContextOpts() *ContextOpts {
	return &ContextOpts{
		Color:    &ColorFlag,
		DryRun:   &DryRunFlag,
		Env:      map[string]string{},
		Manifest: &ManifestFlag,
		Stdin:    os.Stdin,
		Stdout:   os.Stdout,
		Stderr:   os.Stderr,
		Verbose:  &VerboseFlag,
		Timer:    nil,
	}
}

// initOpts initializes all unset options to the given defaults.
func initOpts(defaultOpts, opts *ContextOpts) {
	if opts.Color == nil {
		opts.Color = defaultOpts.Color
	}
	if opts.DryRun == nil {
		opts.DryRun = defaultOpts.DryRun
	}
	if opts.Env == nil {
		opts.Env = defaultOpts.Env
	}
	if opts.Manifest == nil {
		opts.Manifest = defaultOpts.Manifest
	}
	if opts.Stdin == nil {
		opts.Stdin = defaultOpts.Stdin
	}
	if opts.Stdout == nil {
		opts.Stdout = defaultOpts.Stdout
	}
	if opts.Stderr == nil {
		opts.Stderr = defaultOpts.Stderr
	}
	if opts.Verbose == nil {
		opts.Verbose = defaultOpts.Verbose
	}
	if opts.Timer == nil {
		opts.Timer = defaultOpts.Timer
	}
}

// NewContext is the Context factory.
func NewContext(opts ContextOpts) *Context {
	initOpts(newContextOpts(), &opts)
	run := runutil.NewRun(opts.Env, opts.Stdin, opts.Stdout, opts.Stderr, *opts.Color, *opts.DryRun, *opts.Verbose)
	start := runutil.NewStart(opts.Env, opts.Stdin, opts.Stdout, opts.Stderr, *opts.Color, *opts.DryRun, *opts.Verbose)
	return &Context{
		opts:  opts,
		run:   run,
		start: start,
	}
}

// NewContextFromEnv returns a new context instance based on the given
// cmdline environment.
func NewContextFromEnv(env *cmdline.Env) *Context {
	opts := ContextOpts{}
	initOpts(newContextOpts(), &opts)
	opts.Env = envvar.CopyMap(env.Vars)
	opts.Stdin = env.Stdin
	opts.Stdout = env.Stdout
	opts.Stderr = env.Stderr
	opts.Timer = env.Timer
	return NewContext(opts)
}

// NewDefaultContext returns a new default context.
func NewDefaultContext() *Context {
	return NewContext(ContextOpts{})
}

// Clone creates a clone of the given context, overriding select
// settings using the given options.
func (ctx Context) Clone(opts ContextOpts) *Context {
	initOpts(&ctx.opts, &opts)
	return NewContext(opts)
}

// Color returns the color setting of the context.
func (ctx Context) Color() bool {
	return *ctx.opts.Color
}

// DryRun returns the dry run setting of the context.
func (ctx Context) DryRun() bool {
	return *ctx.opts.DryRun
}

// Env returns the environment of the context.
func (ctx Context) Env() map[string]string {
	return ctx.opts.Env
}

// Gerrit returns the Gerrit instance of the context.
func (ctx Context) Gerrit(host string) *gerrit.Gerrit {
	return gerrit.New(ctx.run, host)
}

type gitOpt interface {
	gitOpt()
}
type AuthorDateOpt string
type CommitterDateOpt string
type RootDirOpt string

func (AuthorDateOpt) gitOpt()    {}
func (CommitterDateOpt) gitOpt() {}
func (RootDirOpt) gitOpt()       {}

// Git returns a new git instance.
//
// This method accepts one optional argument: the repository root to
// use for commands issued by the returned instance. If not specified,
// commands will use the current directory as the repository root.
func (ctx Context) Git(opts ...gitOpt) *gitutil.Git {
	rootDir := ""
	gitCtx := &ctx
	for _, opt := range opts {
		switch typedOpt := opt.(type) {
		case AuthorDateOpt:
			opts := ContextOpts{}
			opts.Env = ctx.Env()
			opts.Env["GIT_AUTHOR_DATE"] = string(typedOpt)
			gitCtx = ctx.Clone(opts)
		case CommitterDateOpt:
			opts := ContextOpts{}
			opts.Env = ctx.Env()
			opts.Env["GIT_COMMITTER_DATE"] = string(typedOpt)
			gitCtx = ctx.Clone(opts)
		case RootDirOpt:
			rootDir = string(typedOpt)
		}
	}
	return gitutil.New(gitCtx.run, rootDir)
}

// Jenkins returns a new Jenkins instance that can be used to
// communicate with a Jenkins server running at the given host.
func (ctx Context) Jenkins(host string) (*jenkins.Jenkins, error) {
	return jenkins.New(host)
}

// Manifest returns the manifest of the context.
func (ctx Context) Manifest() string {
	return *ctx.opts.Manifest
}

// Run returns the run instance of the context.
func (ctx Context) Run() *runutil.Run {
	return ctx.run
}

// NewSeq returns a new instance of Sequence initialized using the options
// stored in the context.
func (ctx Context) NewSeq() *runutil.Sequence {
	return runutil.NewSequence(ctx.opts.Env, ctx.opts.Stdin, ctx.opts.Stdout, ctx.opts.Stderr, *ctx.opts.Color, *ctx.opts.DryRun, *ctx.opts.Verbose)
}

// Start returns the start instance of the context.
func (ctx Context) Start() *runutil.Start {
	return ctx.start
}

// Stdin returns the standard input of the context.
func (ctx Context) Stdin() io.Reader {
	return ctx.opts.Stdin
}

// Stdout returns the standard output of the context.
func (ctx Context) Stdout() io.Writer {
	return ctx.opts.Stdout
}

// Stderr returns the standard error output of the context.
func (ctx Context) Stderr() io.Writer {
	return ctx.opts.Stderr
}

// Verbose returns the verbosity setting of the context.
func (ctx Context) Verbose() bool {
	return *ctx.opts.Verbose
}

// Timer returns the timer associated with the context, which may be nil.
func (ctx Context) Timer() *timing.Timer {
	return ctx.opts.Timer
}

// TimerPush calls ctx.Timer().Push(name), only if the Timer is non-nil.
func (ctx Context) TimerPush(name string) {
	if ctx.opts.Timer != nil {
		ctx.opts.Timer.Push(name)
	}
}

// TimerPop calls ctx.Timer().Pop(), only if the Timer is non-nil.
func (ctx Context) TimerPop() {
	if ctx.opts.Timer != nil {
		ctx.opts.Timer.Pop()
	}
}
