// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"

	"thinfs/block/file"
	"thinfs/fs"
	"thinfs/fs/msdosfs"
	"thinfs/fs/msdosfs/clock"
)

var (
	mkfs          = flag.String("mkfs", "", "Path to mkfs-msdosfs host tool from Zircon")
	target        = flag.String("output", "", "Target file/disk to write EFI partition to")
	size          = flag.Uint64("size", 0, "(optional) Size of partition to create")
	offset        = flag.Uint64("offset", 0, "(optional) Offset into target to write partition to")
	zircon        = flag.String("zircon", "", "(optional) Path to source file for zircon.bin")
	bootdata      = flag.String("bootdata", "", "(optional) Path to source file for bootdata.bin")
	efiBootloader = flag.String("efi-bootloader", "", "(optional) Path to source file for EFI/BOOT/BOOTX64.EFI")
	manifest      = flag.String("manifest", "", "(optional) Path to a manifest file of the form `dst=src\n` to import to partition")
	zedboot       = flag.String("zedboot", "", "(optional) Path to a source file for zedboot.bin")
	cmdline       = flag.String("cmdline", "", "(optional) Bootloader cmdline file")
	timestamp     = flag.Int64("timestamp", -1, "(optional) Unix timestamp in seconds used to "+
		"create all files. The actual timestamp used may be different due to FAT32's limit time "+
		"granularity")
)

// minSize is the minimum image size, as the tool currently always builds fat32.
const minSize = 63 * 1024 * 1024

// Fudge factor (percentage) to account for filesystem metadata.
const fudgeFactor = 5

type fixedClock struct {
	now time.Time
}

func (c *fixedClock) Now() time.Time {
	return c.now
}

func main() {
	flag.Parse()

	if *target == "" || *mkfs == "" {
		flag.CommandLine.Usage()
		fmt.Printf("\nerror: -target and -mkfs are required\n")
		os.Exit(1)
	}

	var err error
	*mkfs, err = filepath.Abs(*mkfs)
	if err != nil {
		log.Fatal(err)
	}
	*target, err = filepath.Abs(*target)
	if err != nil {
		log.Fatal(err)
	}

	// Slurp up all the copies to do, as it will make the final copy code simpler.
	// It can also be used to compute the size if the size was not given.
	dstSrc := map[string]string{}
	if *zircon != "" {
		dstSrc["zircon.bin"] = *zircon
	}
	if *bootdata != "" {
		dstSrc["bootdata.bin"] = *bootdata
	}
	if *efiBootloader != "" {
		dstSrc["EFI/BOOT/BOOTX64.EFI"] = *efiBootloader

		tf, err := ioutil.TempFile("", "gsetup-boot")
		if err != nil {
			log.Fatal(err)
		}
		tf.WriteString("efi\\boot\\bootx64.efi")
		tf.Close()
		defer os.Remove(tf.Name())
		dstSrc["EFI/Google/GSetup/Boot"] = tf.Name()
	}
	if *zedboot != "" {
		dstSrc["zedboot.bin"] = *zedboot
	}
	if *cmdline != "" {
		dstSrc["cmdline"] = *cmdline
	}
	if *manifest != "" {
		r, err := newManifestReader(*manifest)
		if err != nil {
			log.Fatal(err)
		}
		for {
			dst, src, err := r.Next()
			if dst != "" && src != "" {
				dstSrc[dst] = src
			}
			if err == io.EOF {
				break
			}
			if err != nil {
				log.Fatal(err)
			}
		}
		r.Close()
	}

	if *size == 0 {
		*size = computeSize(dstSrc)
	}
	*size = alignSize(*size)

	if *timestamp >= 0 {
		now := time.Unix(*timestamp, 0)

		// FAT32 starts at 1980-01-01 to 2107-12-31, so clamp to that range.
		if now.Year() < 1980 {
			now = time.Date(1980, 1, 1, 0, 0, 0, 0, time.Local)
		} else if now.Year() > 2107 {
			now = time.Date(2107, 12, 31, 23, 59, 58, 0, time.Local)
		}

		// FAT stores modification time at 2s granularity
		now = now.Truncate(time.Second * 2)

		clock.Now = func() time.Time {
			return now
		}
	}

	f, err := os.Create(*target)
	if err != nil {
		log.Fatal(err)
	}
	f.Close()

	args := []string{*mkfs,
		"-@", strconv.FormatUint(*offset, 10),
		"-S", strconv.FormatUint(*size, 10),
		"-F", "32",
		"-L", "ESP",
		"-O", "Fuchsia",
		"-b", "512",
	}

	if *timestamp >= 0 {
		args = append(args, "-T", strconv.FormatInt(*timestamp, 10))
	}

	args = append(args, *target)

	cmd := exec.Command(args[0], args[1:]...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		os.Stderr.Write(output)
		log.Fatalf("mkfs did not succceed, see output above.\n%s\n", strings.Join(args, " "))
	}

	f, err = os.OpenFile(*target, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		log.Fatal(err)
	}
	dev, err := file.NewRange(f, 512, int64(*offset), int64(*size))
	if err != nil {
		log.Fatal(err)
	}

	fatfs, err := msdosfs.New(*target, dev, fs.ReadWrite|fs.Force)
	if err != nil {
		log.Fatal(err)
	}

	// Sort the files we are going to copy to make sure the EFI partition
	// is reproducible.
	var dsts []string
	for dst := range dstSrc {
		dsts = append(dsts, dst)
	}
	sort.Strings(dsts)

	root := fatfs.RootDirectory()
	for _, dst := range dsts {
		msCopyIn(root, dstSrc[dst], dst)
	}

	root.Sync()
	if err := root.Close(); err != nil {
		log.Fatal(err)
	}
	if err := fatfs.Close(); err != nil {
		log.Fatal(err)
	}
	f.Sync()
	if err := f.Close(); err != nil {
		log.Fatal(err)
	}
}

// msCopyIn copies src from the host filesystem into dst under the given
// msdosfs root.
func msCopyIn(root fs.Directory, src, dst string) {
	d := root
	defer d.Sync()

	dStack := []fs.Directory{}

	defer func() {
		for _, d := range dStack {
			d.Sync()
			d.Close()
		}
	}()

	destdir := filepath.Dir(dst)
	name := filepath.Base(dst)

	for _, part := range strings.Split(destdir, "/") {
		if part == "." {
			continue
		}

		var err error
		_, d, _, err = d.Open(part, fs.OpenFlagRead|fs.OpenFlagCreate|fs.OpenFlagDirectory)
		if err != nil {
			log.Fatalf("open/create %s: %#v %s", part, err, err)
		}
		d.Sync()
		dStack = append(dStack, d)
	}

	to, _, _, err := d.Open(name, fs.OpenFlagWrite|fs.OpenFlagCreate|fs.OpenFlagFile)
	if err != nil {
		log.Fatalf("creating %s in msdosfs: %s", name, err)
	}
	defer to.Close()

	from, err := os.Open(src)
	if err != nil {
		log.Fatal(err)
	}
	defer from.Close()

	b := make([]byte, 4096)
	for err == nil {
		var n int
		n, err = from.Read(b)
		if n > 0 {
			if _, err := to.Write(b[:n], 0, fs.WhenceFromCurrent); err != nil {
				log.Fatalf("writing %s to msdosfs file: %s", name, err)
			}
		}
	}
	to.Sync()
	if err != nil && err != io.EOF {
		log.Fatal(err)
	}
}

func getSize(f string) uint64 {
	if f == "" {
		return 0
	}
	fi, err := os.Stat(f)
	if err != nil {
		log.Fatal(err)
	}
	return uint64(fi.Size())
}

type manifestReader struct {
	*os.File
	*bufio.Reader
	manifestRoot string
}

func newManifestReader(path string) (*manifestReader, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	return &manifestReader{
		f,
		bufio.NewReader(f),
		filepath.Dir(path),
	}, nil
}

func (r *manifestReader) Next() (dst, src string, err error) {
	for err == nil {
		line, err := r.ReadString('\n')
		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "#") {
			continue
		}
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			log.Printf("make-efi: bad manifest line format: %q, skipping", line)
			continue
		}
		return parts[0], filepath.Join(r.manifestRoot, parts[1]), err
	}
	return "", "", err
}

func computeSize(dstSrc map[string]string) uint64 {
	var total uint64
	for _, src := range dstSrc {
		total += getSize(src)
	}
	total += total * 100 / fudgeFactor
	pad := total % 63
	if pad != 0 {
		total += pad
	}
	if total < minSize {
		return minSize
	}

	return total
}

// sectors per track is 63, and a sector is 512, so we must round to the nearest
// 32256.
const sizeAlignment = 32256

func alignSize(total uint64) uint64 {
	if d := total % sizeAlignment; d != 0 {
		total = total + (sizeAlignment - d)
	}
	return total
}
