package libcontainerd

import (
	"io"
	"strconv"
	"strings"
	"sync"

	"github.com/Microsoft/hcsshim"
)

// process keeps the state for both main container process and exec process.
type process struct {
	processCommon

	// Platform specific fields are below here.

	// commandLine is to support returning summary information for docker top
	commandLine string
	hcsProcess  hcsshim.Process
}

type autoClosingReader struct {
	io.ReadCloser
	sync.Once
}

func (r *autoClosingReader) Read(b []byte) (n int, err error) {
	n, err = r.ReadCloser.Read(b)
	if err == io.EOF {
		r.Once.Do(func() { r.ReadCloser.Close() })
	}
	return
}

// fixStdinBackspaceBehavior works around a bug in Windows before build 14350
// where it interpreted DEL as VK_DELETE instead of as VK_BACK. This replaces
// DEL with BS to work around this.
func fixStdinBackspaceBehavior(w io.WriteCloser, osversion string, tty bool) io.WriteCloser {
	if !tty {
		return w
	}
	v := strings.Split(osversion, ".")
	if len(v) < 3 {
		return w
	}

	if build, err := strconv.Atoi(v[2]); err != nil || build >= 14350 {
		return w
	}

	return &delToBsWriter{w}
}

type delToBsWriter struct {
	io.WriteCloser
}

func (w *delToBsWriter) Write(b []byte) (int, error) {
	const (
		backspace = 0x8
		del       = 0x7f
	)
	bc := make([]byte, len(b))
	for i, c := range b {
		if c == del {
			bc[i] = backspace
		} else {
			bc[i] = c
		}
	}
	return w.WriteCloser.Write(bc)
}

type stdInCloser struct {
	io.WriteCloser
	hcsshim.Process
}

func createStdInCloser(pipe io.WriteCloser, process hcsshim.Process) *stdInCloser {
	return &stdInCloser{
		WriteCloser: pipe,
		Process:     process,
	}
}

func (stdin *stdInCloser) Close() error {
	if err := stdin.WriteCloser.Close(); err != nil {
		return err
	}

	return stdin.Process.CloseStdin()
}

func (stdin *stdInCloser) Write(p []byte) (n int, err error) {
	return stdin.WriteCloser.Write(p)
}