// 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 runutil

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
)

// helper executes the given Go standard library function,
// encapsulated as a closure, respecting the "dry run" option.
func (r *Run) helper(fn func() error, format string, args ...interface{}) error {
	if opts := r.opts; opts.DryRun {
		opts.Verbose = true
		return r.FunctionWithOpts(opts, func() error { return nil }, format, args...)
	}
	return r.Function(fn, format, args...)
}

// dryRun executes the given Go standard library function, encapsulated as a
// closure, but translating "dry run" into "verbose" for this particular
// command so that the command can execute and thus allow subsequent
// commands to complete. It is generally used for testing/making files/directories
// that affect subsequent behaviour.
func (r *Run) dryRun(fn func() error, format string, args ...interface{}) error {
	if opts := r.opts; opts.DryRun {
		// Disable the dry run option as this function has no effect and
		// doing so results in more informative "dry run" output.
		opts.DryRun = false
		opts.Verbose = true
		return r.FunctionWithOpts(opts, fn, format, args...)
	}
	return r.Function(fn, format, args...)
}

// Chdir is a wrapper around os.Chdir that handles options such as
// "verbose" or "dry run".
func (r *Run) Chdir(dir string) error {
	return r.dryRun(func() error {
		return os.Chdir(dir)
	}, fmt.Sprintf("cd %q", dir))
}

// Chmod is a wrapper around os.Chmod that handles options such as
// "verbose" or "dry run".
func (r *Run) Chmod(dir string, mode os.FileMode) error {
	return r.helper(func() error { return os.Chmod(dir, mode) }, fmt.Sprintf("chmod %v %q", mode, dir))
}

// Create is a wrapper around os.Create that handles options such as "verbose"
// or "dry run".
func (r *Run) Create(name string) (f *os.File, err error) {
	r.helper(func() error {
		f, err = os.Create(name)
		return err
	}, fmt.Sprintf("create %q", name))
	return
}

// Copy is a wrapper around io.Copy that handles options such as "verbose" or
// "dry run".
func (r *Run) Copy(dst *os.File, src io.Reader) (n int64, err error) {
	r.helper(func() error {
		n, err = io.Copy(dst, src)
		return err
	}, fmt.Sprintf("io.copy %q", dst.Name()))
	return
}

// MkdirAll is a wrapper around os.MkdirAll that handles options such
// as "verbose" or "dry run".
func (r *Run) MkdirAll(dir string, mode os.FileMode) error {
	return r.helper(func() error { return os.MkdirAll(dir, mode) }, fmt.Sprintf("mkdir -p %q", dir))
}

// Open is a wrapper around os.Open that handles options such as
// "verbose" or "dry run".
func (r *Run) Open(name string) (f *os.File, err error) {
	r.helper(func() error {
		f, err = os.Open(name)
		return err
	}, fmt.Sprintf("open %q", name))
	return
}

// OpenFile is a wrapper around os.OpenFile that handles options such as
// "verbose" or "dry run".
func (r *Run) OpenFile(name string, flag int, perm os.FileMode) (f *os.File, err error) {
	r.helper(func() error {
		f, err = os.OpenFile(name, flag, perm)
		return err
	}, fmt.Sprintf("open file %q", name))
	return
}

// ReadDir is a wrapper around ioutil.ReadDir that handles options
// such as "verbose" or "dry run".
func (r *Run) ReadDir(dirname string) (fileInfos []os.FileInfo, err error) {
	r.dryRun(func() error {
		fileInfos, err = ioutil.ReadDir(dirname)
		return err
	}, fmt.Sprintf("ls %q", dirname))
	return
}

// ReadFile is a wrapper around ioutil.ReadFile that handles options
// such as "verbose" or "dry run".
func (r *Run) ReadFile(filename string) (bytes []byte, err error) {
	r.dryRun(func() error {
		bytes, err = ioutil.ReadFile(filename)
		return err
	}, fmt.Sprintf("read %q", filename))
	return
}

// RemoveAll is a wrapper around os.RemoveAll that handles options
// such as "verbose" or "dry run".
func (r *Run) RemoveAll(dir string) error {
	return r.helper(func() error { return os.RemoveAll(dir) }, fmt.Sprintf("rm -rf %q", dir))
}

// Remove is a wrapper around os.Remove that handles options
// such as "verbose" or "dry run".
func (r *Run) Remove(file string) error {
	return r.helper(func() error { return os.Remove(file) }, fmt.Sprintf("rm %q", file))
}

// Rename is a wrapper around os.Rename that handles options such as
// "verbose" or "dry run".
func (r *Run) Rename(src, dst string) error {
	return r.helper(func() error {
		if err := os.Rename(src, dst); err != nil {
			// Check if the rename operation failed
			// because the source and destination are
			// located on different mount points.
			linkErr, ok := err.(*os.LinkError)
			if !ok {
				return err
			}
			errno, ok := linkErr.Err.(syscall.Errno)
			if !ok || errno != syscall.EXDEV {
				return err
			}
			// Fall back to a non-atomic rename.
			cmd := exec.Command("mv", src, dst)
			return cmd.Run()
		}
		return nil
	}, fmt.Sprintf("mv %q %q", src, dst))
}

// Stat is a wrapper around os.Stat that handles options such as
// "verbose" or "dry run".
func (r *Run) Stat(name string) (fileInfo os.FileInfo, err error) {
	r.dryRun(func() error {
		fileInfo, err = os.Stat(name)
		return err
	}, fmt.Sprintf("stat %q", name))
	return
}

// Lstat is a wrapper around os.Lstat that handles options such as
// "verbose" or "dry run".
func (r *Run) Lstat(name string) (fileInfo os.FileInfo, err error) {
	r.dryRun(func() error {
		fileInfo, err = os.Lstat(name)
		return err
	}, fmt.Sprintf("lstat %q", name))
	return
}

// Readlink is a wrapper around os.Readlink that handles options such as
// "verbose" or "dry run".
func (r *Run) Readlink(name string) (link string, err error) {
	r.dryRun(func() error {
		link, err = os.Readlink(name)
		return err
	}, fmt.Sprintf("readlink %q", name))
	return
}

// IsDir is a wrapper around os.Stat that handles options such as
// "verbose" or "dry run".
func (r *Run) IsDir(name string) (bool, error) {
	var fileInfo os.FileInfo
	var err error
	r.dryRun(func() error {
		fileInfo, err = os.Stat(name)
		return err
	}, fmt.Sprintf("isdir %q", name))
	if err != nil {
		return false, err
	}
	return fileInfo.IsDir(), err
}

// Symlink is a wrapper around os.Symlink that handles options such as
// "verbose" or "dry run".
func (r *Run) Symlink(src, dst string) error {
	return r.helper(func() error { return os.Symlink(src, dst) }, fmt.Sprintf("ln -s %q %q", src, dst))
}

// TempDir is a wrapper around ioutil.TempDir that handles options
// such as "verbose" or "dry run".
func (r *Run) TempDir(dir, prefix string) (tmpDir string, err error) {
	if dir == "" {
		dir = os.Getenv("TMPDIR")
	}
	tmpDir = filepath.Join(dir, prefix+"XXXXXX")
	r.helper(func() error {
		tmpDir, err = ioutil.TempDir(dir, prefix)
		return err
	}, fmt.Sprintf("mkdir -p %q", tmpDir))
	return
}

// TempFile is a wrapper around ioutil.TempFile that handles options
// such as "verbose" or "dry run".
func (r *Run) TempFile(dir, prefix string) (f *os.File, err error) {
	r.helper(func() error {
		f, err = ioutil.TempFile(dir, prefix)
		return err
	}, fmt.Sprintf("open %q", f.Name()))
	return
}

// WriteFile is a wrapper around ioutil.WriteFile that handles options
// such as "verbose" or "dry run".
func (r *Run) WriteFile(filename string, data []byte, perm os.FileMode) error {
	return r.helper(func() error {
		return ioutil.WriteFile(filename, data, perm)
	}, fmt.Sprintf("write %q", filename))
}

// DirectoryExists tests if a directory exists with appropriate logging.
func (r *Run) DirectoryExists(dir string) bool {
	isdir, err := r.IsDir(dir)
	if err != nil {
		return false
	}
	return isdir
}

// FileExists tests if a file exists with appropriate logging.
func (r *Run) FileExists(file string) bool {
	_, err := r.Stat(file)
	return err == nil
}
