// Copyright 2018 The CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package load

import (
	"bytes"
	"go/ast"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
)

type overlayFile struct {
	basename string
	contents []byte
	file     *ast.File
	modtime  time.Time
	isDir    bool
}

func (f *overlayFile) Name() string       { return f.basename }
func (f *overlayFile) Size() int64        { return int64(len(f.contents)) }
func (f *overlayFile) Mode() os.FileMode  { return 0644 }
func (f *overlayFile) ModTime() time.Time { return f.modtime }
func (f *overlayFile) IsDir() bool        { return f.isDir }
func (f *overlayFile) Sys() interface{}   { return nil }

// A fileSystem specifies the supporting context for a build.
type fileSystem struct {
	overlayDirs map[string]map[string]*overlayFile
	cwd         string
}

func (fs *fileSystem) getDir(dir string, create bool) map[string]*overlayFile {
	dir = filepath.Clean(dir)
	m, ok := fs.overlayDirs[dir]
	if !ok && create {
		m = map[string]*overlayFile{}
		fs.overlayDirs[dir] = m
	}
	return m
}

func (fs *fileSystem) init(c *Config) error {
	fs.cwd = c.Dir

	overlay := c.Overlay
	fs.overlayDirs = map[string]map[string]*overlayFile{}

	// Organize overlay
	for filename, src := range overlay {
		// TODO: do we need to further clean the path or check that the
		// specified files are within the root/ absolute files?
		dir, base := filepath.Split(filename)
		m := fs.getDir(dir, true)

		b, err := src.contents()
		if err != nil {
			return err
		}
		m[base] = &overlayFile{
			basename: base,
			contents: b,
			modtime:  time.Now(),
		}

		for {
			prevdir := dir
			dir, base = filepath.Split(filepath.Dir(dir))
			if dir == prevdir || dir == "" {
				break
			}
			m := fs.getDir(dir, true)
			if m[base] == nil {
				m[base] = &overlayFile{
					basename: base,
					modtime:  time.Now(),
					isDir:    true,
				}
			}
		}
	}
	return nil
}

func (fs *fileSystem) joinPath(elem ...string) string {
	return filepath.Join(elem...)
}

func (fs *fileSystem) splitPathList(s string) []string {
	return filepath.SplitList(s)
}

func (fs *fileSystem) isAbsPath(path string) bool {
	return filepath.IsAbs(path)
}

func (fs *fileSystem) makeAbs(path string) string {
	if fs.isAbsPath(path) {
		return path
	}
	return filepath.Clean(filepath.Join(fs.cwd, path))
}

func (fs *fileSystem) isDir(path string) bool {
	path = fs.makeAbs(path)
	if fs.getDir(path, false) != nil {
		return true
	}
	fi, err := os.Stat(path)
	return err == nil && fi.IsDir()
}

func (fs *fileSystem) hasSubdir(root, dir string) (rel string, ok bool) {
	// Try using paths we received.
	if rel, ok = hasSubdir(root, dir); ok {
		return
	}

	// Try expanding symlinks and comparing
	// expanded against unexpanded and
	// expanded against expanded.
	rootSym, _ := filepath.EvalSymlinks(root)
	dirSym, _ := filepath.EvalSymlinks(dir)

	if rel, ok = hasSubdir(rootSym, dir); ok {
		return
	}
	if rel, ok = hasSubdir(root, dirSym); ok {
		return
	}
	return hasSubdir(rootSym, dirSym)
}

func hasSubdir(root, dir string) (rel string, ok bool) {
	const sep = string(filepath.Separator)
	root = filepath.Clean(root)
	if !strings.HasSuffix(root, sep) {
		root += sep
	}
	dir = filepath.Clean(dir)
	if !strings.HasPrefix(dir, root) {
		return "", false
	}
	return filepath.ToSlash(dir[len(root):]), true
}

func (fs *fileSystem) readDir(path string) ([]os.FileInfo, errors.Error) {
	path = fs.makeAbs(path)
	m := fs.getDir(path, false)
	items, err := ioutil.ReadDir(path)
	if err != nil {
		if !os.IsNotExist(err) || m == nil {
			return nil, errors.Wrapf(err, token.NoPos, "readDir")
		}
	}
	if m != nil {
		done := map[string]bool{}
		for i, fi := range items {
			done[fi.Name()] = true
			if o := m[fi.Name()]; o != nil {
				items[i] = o
			}
		}
		for _, o := range m {
			if !done[o.Name()] {
				items = append(items, o)
			}
		}
		sort.Slice(items, func(i, j int) bool {
			return items[i].Name() < items[j].Name()
		})
	}
	return items, nil
}

func (fs *fileSystem) getOverlay(path string) *overlayFile {
	dir, base := filepath.Split(path)
	if m := fs.getDir(dir, false); m != nil {
		return m[base]
	}
	return nil
}

func (fs *fileSystem) stat(path string) (os.FileInfo, errors.Error) {
	path = fs.makeAbs(path)
	if fi := fs.getOverlay(path); fi != nil {
		return fi, nil
	}
	fi, err := os.Stat(path)
	if err != nil {
		return nil, errors.Wrapf(err, token.NoPos, "stat")
	}
	return fi, nil
}

func (fs *fileSystem) lstat(path string) (os.FileInfo, errors.Error) {
	path = fs.makeAbs(path)
	if fi := fs.getOverlay(path); fi != nil {
		return fi, nil
	}
	fi, err := os.Lstat(path)
	if err != nil {
		return nil, errors.Wrapf(err, token.NoPos, "stat")
	}
	return fi, nil
}

func (fs *fileSystem) openFile(path string) (io.ReadCloser, errors.Error) {
	path = fs.makeAbs(path)
	if fi := fs.getOverlay(path); fi != nil {
		return ioutil.NopCloser(bytes.NewReader(fi.contents)), nil
	}

	f, err := os.Open(path)
	if err != nil {
		return nil, errors.Wrapf(err, token.NoPos, "load")
	}
	return f, nil
}

var skipDir = errors.Newf(token.NoPos, "skip directory")

type walkFunc func(path string, info os.FileInfo, err errors.Error) errors.Error

func (fs *fileSystem) walk(root string, f walkFunc) error {
	fi, err := fs.lstat(root)
	if err != nil {
		err = f(root, fi, err)
	} else if !fi.IsDir() {
		return errors.Newf(token.NoPos, "path %q is not a directory", root)
	} else {
		err = fs.walkRec(root, fi, f)
	}
	if err == skipDir {
		return nil
	}
	return err

}

func (fs *fileSystem) walkRec(path string, info os.FileInfo, f walkFunc) errors.Error {
	if !info.IsDir() {
		return f(path, info, nil)
	}

	dir, err := fs.readDir(path)
	err1 := f(path, info, err)

	// If err != nil, walk can't walk into this directory.
	// err1 != nil means walkFn want walk to skip this directory or stop walking.
	// Therefore, if one of err and err1 isn't nil, walk will return.
	if err != nil || err1 != nil {
		// The caller's behavior is controlled by the return value, which is decided
		// by walkFn. walkFn may ignore err and return nil.
		// If walkFn returns SkipDir, it will be handled by the caller.
		// So walk should return whatever walkFn returns.
		return err1
	}

	for _, info := range dir {
		filename := fs.joinPath(path, info.Name())
		err = fs.walkRec(filename, info, f)
		if err != nil {
			if !info.IsDir() || err != skipDir {
				return err
			}
		}
	}
	return nil
}
