// +build windows

package lcow // import "github.com/docker/docker/daemon/graphdriver/lcow"

import (
	"errors"
	"os"
	pathpkg "path"
	"path/filepath"
	"sort"
	"strings"

	"github.com/containerd/continuity/pathdriver"
)

var _ pathdriver.PathDriver = &lcowfs{}

// Continuity Path functions can be done locally
func (l *lcowfs) Join(path ...string) string {
	return pathpkg.Join(path...)
}

func (l *lcowfs) IsAbs(path string) bool {
	return pathpkg.IsAbs(path)
}

func sameWord(a, b string) bool {
	return a == b
}

// Implementation taken from the Go standard library
func (l *lcowfs) Rel(basepath, targpath string) (string, error) {
	baseVol := ""
	targVol := ""
	base := l.Clean(basepath)
	targ := l.Clean(targpath)
	if sameWord(targ, base) {
		return ".", nil
	}
	base = base[len(baseVol):]
	targ = targ[len(targVol):]
	if base == "." {
		base = ""
	}
	// Can't use IsAbs - `\a` and `a` are both relative in Windows.
	baseSlashed := len(base) > 0 && base[0] == l.Separator()
	targSlashed := len(targ) > 0 && targ[0] == l.Separator()
	if baseSlashed != targSlashed || !sameWord(baseVol, targVol) {
		return "", errors.New("Rel: can't make " + targpath + " relative to " + basepath)
	}
	// Position base[b0:bi] and targ[t0:ti] at the first differing elements.
	bl := len(base)
	tl := len(targ)
	var b0, bi, t0, ti int
	for {
		for bi < bl && base[bi] != l.Separator() {
			bi++
		}
		for ti < tl && targ[ti] != l.Separator() {
			ti++
		}
		if !sameWord(targ[t0:ti], base[b0:bi]) {
			break
		}
		if bi < bl {
			bi++
		}
		if ti < tl {
			ti++
		}
		b0 = bi
		t0 = ti
	}
	if base[b0:bi] == ".." {
		return "", errors.New("Rel: can't make " + targpath + " relative to " + basepath)
	}
	if b0 != bl {
		// Base elements left. Must go up before going down.
		seps := strings.Count(base[b0:bl], string(l.Separator()))
		size := 2 + seps*3
		if tl != t0 {
			size += 1 + tl - t0
		}
		buf := make([]byte, size)
		n := copy(buf, "..")
		for i := 0; i < seps; i++ {
			buf[n] = l.Separator()
			copy(buf[n+1:], "..")
			n += 3
		}
		if t0 != tl {
			buf[n] = l.Separator()
			copy(buf[n+1:], targ[t0:])
		}
		return string(buf), nil
	}
	return targ[t0:], nil
}

func (l *lcowfs) Base(path string) string {
	return pathpkg.Base(path)
}

func (l *lcowfs) Dir(path string) string {
	return pathpkg.Dir(path)
}

func (l *lcowfs) Clean(path string) string {
	return pathpkg.Clean(path)
}

func (l *lcowfs) Split(path string) (dir, file string) {
	return pathpkg.Split(path)
}

func (l *lcowfs) Separator() byte {
	return '/'
}

func (l *lcowfs) Abs(path string) (string, error) {
	// Abs is supposed to add the current working directory, which is meaningless in lcow.
	// So, return an error.
	return "", ErrNotSupported
}

// Implementation taken from the Go standard library
func (l *lcowfs) Walk(root string, walkFn filepath.WalkFunc) error {
	info, err := l.Lstat(root)
	if err != nil {
		err = walkFn(root, nil, err)
	} else {
		err = l.walk(root, info, walkFn)
	}
	if err == filepath.SkipDir {
		return nil
	}
	return err
}

// walk recursively descends path, calling w.
func (l *lcowfs) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
	err := walkFn(path, info, nil)
	if err != nil {
		if info.IsDir() && err == filepath.SkipDir {
			return nil
		}
		return err
	}

	if !info.IsDir() {
		return nil
	}

	names, err := l.readDirNames(path)
	if err != nil {
		return walkFn(path, info, err)
	}

	for _, name := range names {
		filename := l.Join(path, name)
		fileInfo, err := l.Lstat(filename)
		if err != nil {
			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
				return err
			}
		} else {
			err = l.walk(filename, fileInfo, walkFn)
			if err != nil {
				if !fileInfo.IsDir() || err != filepath.SkipDir {
					return err
				}
			}
		}
	}
	return nil
}

// readDirNames reads the directory named by dirname and returns
// a sorted list of directory entries.
func (l *lcowfs) readDirNames(dirname string) ([]string, error) {
	f, err := l.Open(dirname)
	if err != nil {
		return nil, err
	}
	files, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, err
	}

	names := make([]string, len(files), len(files))
	for i := range files {
		names[i] = files[i].Name()
	}

	sort.Strings(names)
	return names, nil
}

// Note that Go's filepath.FromSlash/ToSlash convert between OS paths and '/'. Since the path separator
// for LCOW (and Unix) is '/', they are no-ops.
func (l *lcowfs) FromSlash(path string) string {
	return path
}

func (l *lcowfs) ToSlash(path string) string {
	return path
}

func (l *lcowfs) Match(pattern, name string) (matched bool, err error) {
	return pathpkg.Match(pattern, name)
}
