// Copyright 2016 Google Inc. All rights reserved.
//
// 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 fs

import (
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sync"

	"github.com/google/slothfs/cache"
	"github.com/google/slothfs/gitiles"
	"github.com/google/slothfs/manifest"
	"github.com/hanwen/go-fuse/fuse"
	"github.com/hanwen/go-fuse/fuse/nodefs"
)

type multiManifestFSRoot struct {
	nodefs.Node
	nodeCache *nodeCache
	cache     *cache.Cache
	fsConn    *nodefs.FileSystemConnector
	options   MultiFSOptions
	gitiles   *gitiles.Service
}

func (c *configNode) configureWorkspaces() error {
	if c.root.options.ManifestDir == "" {
		return nil
	}
	fs, err := filepath.Glob(filepath.Join(c.root.options.ManifestDir, "*"))
	if err != nil || len(fs) == 0 {
		return err
	}

	log.Println("configuring workspaces...")
	var wg sync.WaitGroup
	wg.Add(len(fs))
	for _, f := range fs {
		go func(n string) {
			_, code := c.Symlink(filepath.Base(n), n, nil)
			log.Printf("manifest %s: %v", n, code)
			wg.Done()
		}(f)
	}
	wg.Wait()

	return nil
}

func (r *multiManifestFSRoot) OnMount(fsConn *nodefs.FileSystemConnector) {
	r.fsConn = fsConn

	cfg := &configNode{
		Node: nodefs.NewDefaultNode(),
		root: r,
	}
	r.Inode().NewChild("config", true, cfg)

	if err := cfg.configureWorkspaces(); err != nil {
		log.Printf("configureWorkspaces: %v", err)
	}
}

func (c *configNode) Deletable() bool { return false }

func NewMultiFS(service *gitiles.Service, c *cache.Cache, options MultiFSOptions) *multiManifestFSRoot {
	r := &multiManifestFSRoot{
		Node:      nodefs.NewDefaultNode(),
		nodeCache: newNodeCache(),
		cache:     c,
		options:   options,
		gitiles:   service,
	}
	return r
}

func (r *multiManifestFSRoot) Deletable() bool { return false }

func (r *multiManifestFSRoot) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
	return nil, fuse.ENODATA
}

type configNode struct {
	nodefs.Node
	root *multiManifestFSRoot
}

type configEntryNode struct {
	nodefs.Node
	link []byte
}

func (c *configEntryNode) GetAttr(out *fuse.Attr, f nodefs.File, ctx *fuse.Context) fuse.Status {
	out.Mode = fuse.S_IFLNK
	return fuse.OK
}

func (c *configEntryNode) Readlink(ctx *fuse.Context) ([]byte, fuse.Status) {
	return c.link, fuse.OK
}

func (c *configEntryNode) Deletable() bool { return false }

func (c *configNode) Unlink(name string, ctx *fuse.Context) fuse.Status {
	child := c.root.Inode().RmChild(name)
	if child == nil {
		return fuse.ENOENT
	}

	// Notify the kernel this part of the tree disappeared.
	c.root.fsConn.DeleteNotify(c.root.Inode(), child, name)

	c.Inode().RmChild(name)

	// No need to notify for the removed symlink. Since we're in
	// the Unlink method, will VFS already knows about the
	// deletion once we return OK.

	if dir := c.root.options.ManifestDir; dir != "" {
		os.Remove(filepath.Join(dir, name))
	}

	return fuse.OK
}

func (c *configNode) Symlink(name, content string, ctx *fuse.Context) (*nodefs.Inode, fuse.Status) {
	mfBytes, err := ioutil.ReadFile(content)
	if err != nil {
		return nil, fuse.ToStatus(err)
	}

	mf, err := manifest.Parse(mfBytes)
	if err != nil {
		log.Printf("Parse(%s): %v", content, err)
		return nil, fuse.EINVAL
	}

	options := ManifestOptions{
		Manifest:        mf,
		RepoCloneOption: c.root.options.RepoCloneOption,
		FileCloneOption: c.root.options.FileCloneOption,
	}

	fs, err := NewManifestFS(c.root.gitiles, c.root.cache, options)
	if err != nil {
		log.Printf("NewManifestFS(%s): %v", string(content), err)
		return nil, fuse.EIO
	}
	fs.(*manifestFSRoot).nodeCache = c.root.nodeCache

	child := c.root.Inode().NewChild(name, true, fs)
	if child == nil {
		// TODO(hanwen): can this ever happen?
		return nil, fuse.EINVAL
	}

	config := c.Inode().NewChild(name, false, &configEntryNode{
		Node: nodefs.NewDefaultNode(),
		// This is sneaky, but it appears to work.
		link: []byte(filepath.Join("..", name, ".slothfs", "manifest.xml")),
	})

	if err := fs.(*manifestFSRoot).onMount(c.root.fsConn); err != nil {
		log.Printf("onMount(%s): %v", name, err)
		for k := range child.Children() {
			child.RmChild(k)
		}

		child.NewChild("ERROR", false, &dataNode{nodefs.NewDefaultNode(), []byte(err.Error())})
	} else {
		if dir := c.root.options.ManifestDir; dir != "" {
			for {
				f, err := ioutil.TempFile(dir, "")
				if err != nil {
					break
				}

				_, err = f.Write(mfBytes)
				if err != nil {
					break
				}

				if err := f.Close(); err != nil {
					break
				}

				os.Rename(f.Name(), filepath.Join(dir, name))
				break
			}
		}
	}

	c.root.fsConn.EntryNotify(c.root.Inode(), name)

	return config, fuse.OK
}
