// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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.

// mkerofs takes a specification in the form of a prototext file (see fsspec
// next to this) and assembles an EROFS filesystem according to it. The output
// is fully reproducible.
package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"sort"
	"strings"

	"source.monogon.dev/metropolis/node/build/fsspec"
	"source.monogon.dev/metropolis/pkg/erofs"
)

func (spec *entrySpec) writeRecursive(w *erofs.Writer, pathname string) {
	switch inode := spec.data.Type.(type) {
	case *fsspec.Inode_Directory:
		// Sort children for reproducibility
		var sortedChildren []string
		for name := range spec.children {
			sortedChildren = append(sortedChildren, name)
		}
		sort.Strings(sortedChildren)

		err := w.Create(pathname, &erofs.Directory{
			Base: erofs.Base{
				Permissions: uint16(inode.Directory.Mode),
				UID:         uint16(inode.Directory.Uid),
				GID:         uint16(inode.Directory.Gid),
			},
			Children: sortedChildren,
		})
		if err != nil {
			log.Fatalf("failed to write directory: %s", err)
		}
		for _, name := range sortedChildren {
			spec.children[name].writeRecursive(w, path.Join(pathname, name))
		}
	case *fsspec.Inode_File:
		iw := w.CreateFile(pathname, &erofs.FileMeta{
			Base: erofs.Base{
				Permissions: uint16(inode.File.Mode),
				UID:         uint16(inode.File.Uid),
				GID:         uint16(inode.File.Gid),
			},
		})

		sourceFile, err := os.Open(inode.File.SourcePath)
		if err != nil {
			log.Fatalf("failed to open source file %s: %s", inode.File.SourcePath, err)
		}

		_, err = io.Copy(iw, sourceFile)
		if err != nil {
			log.Fatalf("failed to copy file into filesystem: %s", err)
		}
		sourceFile.Close()
		if err := iw.Close(); err != nil {
			log.Fatalf("failed to close target file: %s", err)
		}
	case *fsspec.Inode_SymbolicLink:
		err := w.Create(pathname, &erofs.SymbolicLink{
			Base: erofs.Base{
				Permissions: 0777, // Nominal, Linux forces that mode anyways, see symlink(7)
			},
			Target: inode.SymbolicLink.TargetPath,
		})
		if err != nil {
			log.Fatalf("failed to create symbolic link: %s", err)
		}
	case *fsspec.Inode_SpecialFile:
		err := fmt.Errorf("unimplemented special file type %s", inode.SpecialFile.Type)
		base := erofs.Base{
			Permissions: uint16(inode.SpecialFile.Mode),
			UID:         uint16(inode.SpecialFile.Uid),
			GID:         uint16(inode.SpecialFile.Gid),
		}
		switch inode.SpecialFile.Type {
		case fsspec.SpecialFile_FIFO:
			err = w.Create(pathname, &erofs.FIFO{
				Base: base,
			})
		case fsspec.SpecialFile_CHARACTER_DEV:
			err = w.Create(pathname, &erofs.CharacterDevice{
				Base:  base,
				Major: inode.SpecialFile.Major,
				Minor: inode.SpecialFile.Minor,
			})
		case fsspec.SpecialFile_BLOCK_DEV:
			err = w.Create(pathname, &erofs.BlockDevice{
				Base:  base,
				Major: inode.SpecialFile.Major,
				Minor: inode.SpecialFile.Minor,
			})
		}
		if err != nil {
			log.Fatalf("failed to make special file: %v", err)
		}
	}
}

// entrySpec is a recursive structure representing the filesystem tree
type entrySpec struct {
	data     fsspec.Inode
	children map[string]*entrySpec
}

// pathRef gets the entrySpec at the leaf of the given path, inferring
// directories if necessary
func (s *entrySpec) pathRef(p string) *entrySpec {
	// This block gets a path array starting at the root of the filesystem. The
	// root folder is the zero-length array.
	pathParts := strings.Split(path.Clean("./"+p), "/")
	if pathParts[0] == "." {
		pathParts = pathParts[1:]
	}

	entryRef := s
	for _, part := range pathParts {
		childRef, ok := entryRef.children[part]
		if !ok {
			childRef = &entrySpec{
				data:     fsspec.Inode{Type: &fsspec.Inode_Directory{Directory: &fsspec.Directory{Mode: 0555}}},
				children: make(map[string]*entrySpec),
			}
			entryRef.children[part] = childRef
		}
		entryRef = childRef
	}
	return entryRef
}

var (
	outPath = flag.String("out", "", "Output file path")
)

func main() {
	flag.Parse()

	spec, err := fsspec.ReadMergeSpecs(flag.Args())
	if err != nil {
		log.Fatalf("failed to load specs: %v", err)
	}

	var fsRoot = &entrySpec{
		data:     fsspec.Inode{Type: &fsspec.Inode_Directory{Directory: &fsspec.Directory{Mode: 0555}}},
		children: make(map[string]*entrySpec),
	}

	for _, dir := range spec.Directory {
		entryRef := fsRoot.pathRef(dir.Path)
		entryRef.data.Type = &fsspec.Inode_Directory{Directory: dir}
	}

	for _, file := range spec.File {
		entryRef := fsRoot.pathRef(file.Path)
		entryRef.data.Type = &fsspec.Inode_File{File: file}
	}

	for _, symlink := range spec.SymbolicLink {
		entryRef := fsRoot.pathRef(symlink.Path)
		entryRef.data.Type = &fsspec.Inode_SymbolicLink{SymbolicLink: symlink}
	}

	for _, specialFile := range spec.SpecialFile {
		entryRef := fsRoot.pathRef(specialFile.Path)
		entryRef.data.Type = &fsspec.Inode_SpecialFile{SpecialFile: specialFile}
	}

	fs, err := os.Create(*outPath)
	if err != nil {
		log.Fatalf("failed to open output file: %v", err)
	}
	writer, err := erofs.NewWriter(fs)
	if err != nil {
		log.Fatalf("failed to initialize EROFS writer: %v", err)
	}

	fsRoot.writeRecursive(writer, ".")

	if err := writer.Close(); err != nil {
		panic(err)
	}
	if err := fs.Close(); err != nil {
		panic(err)
	}
}
