// 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 build

import (
	"bufio"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sync"

	"go.fuchsia.dev/fuchsia/src/sys/pkg/bin/pm/pkg"
	"go.fuchsia.dev/fuchsia/src/sys/pkg/lib/far/go"
	"go.fuchsia.dev/fuchsia/src/sys/pkg/lib/merkle"
)

const abiRevisionKey string = "meta/fuchsia.abi/abi-revision"

// PackageManifest is the json structure representation of a full package
// manifest.
type PackageManifest struct {
	Version string            `json:"version"`
	Package pkg.Package       `json:"package"`
	Blobs   []PackageBlobInfo `json:"blobs"`
}

// Init initializes package metadata in the output directory. A manifest
// is generated with a name matching the output directory name.
func Init(cfg *Config) error {
	metadir := filepath.Join(cfg.OutputDir, "meta")
	if err := os.MkdirAll(metadir, os.ModePerm); err != nil {
		return err
	}

	meta := filepath.Join(metadir, "package")
	if _, err := os.Stat(meta); os.IsNotExist(err) {
		f, err := os.Create(meta)
		if err != nil {
			return err
		}

		p, err := cfg.Package()
		if err != nil {
			return err
		}

		err = json.NewEncoder(f).Encode(&p)
		f.Close()
		if err != nil {
			return err
		}
	}
	return nil
}

// Update walks the contents of the package and updates the merkle root values
// within the contents file.
func Update(cfg *Config) error {
	metadir := filepath.Join(cfg.OutputDir, "meta")
	os.MkdirAll(metadir, os.ModePerm)
	manifest, err := cfg.Manifest()
	if err != nil {
		return err
	}

	if err := writeABIRevision(cfg, manifest); err != nil {
		return err
	}

	contentsPath := filepath.Join(metadir, "contents")
	pkgContents := manifest.Content()

	// manifestLines is a channel containing unpacked manifest paths
	var manifestLines = make(chan struct{ src, dest string }, len(pkgContents))
	go func() {
		for dest, src := range pkgContents {
			manifestLines <- struct{ src, dest string }{src, dest}
		}
		close(manifestLines)
	}()

	// contentCollector receives entries to include in contents
	type contentEntry struct {
		path string
		root MerkleRoot
	}
	var contentCollector = make(chan contentEntry, len(pkgContents))
	var errors = make(chan error)

	// w is a group that is done when contentCollector is fully populated
	var w sync.WaitGroup
	for i := runtime.NumCPU(); i > 0; i-- {
		w.Add(1)

		go func() {
			defer w.Done()

			for in := range manifestLines {
				var t merkle.Tree
				cf, err := os.Open(in.src)
				if err != nil {
					errors <- fmt.Errorf("build.Update: open %s for %s: %s", in.src, in.dest, err)
					return
				}
				_, err = t.ReadFrom(bufio.NewReader(cf))
				cf.Close()
				if err != nil {
					errors <- err
					return
				}

				var root MerkleRoot
				copy(root[:], t.Root())
				contentCollector <- contentEntry{in.dest, root}
			}
		}()
	}

	// close the collector channel when all workers are done
	go func() {
		w.Wait()
		close(contentCollector)
	}()

	// collect all results and close done to signal the waiting select
	var done = make(chan struct{})
	contents := MetaContents{}
	go func() {
		for entry := range contentCollector {
			contents[entry.path] = entry.root
		}
		close(done)
	}()

	select {
	case <-done:
		// contents is populated
	case err := <-errors:
		// exit on the first error
		return err
	}

	manifest.Paths["meta/contents"] = contentsPath

	return ioutil.WriteFile(contentsPath,
		[]byte(contents.String()), os.ModePerm)
}

func writeABIRevision(cfg *Config, manifest *Manifest) error {
	// FIXME(): We can stop treating the ABI revision as optional once the
	// ecosystem has migrated to specifying it everywhere.
	if cfg.PkgABIRevision == 0 {
		return nil
	}

	abiDir := filepath.Join(cfg.OutputDir, "meta", "fuchsia.abi")
	os.MkdirAll(abiDir, os.ModePerm)

	b := make([]byte, 8)
	binary.LittleEndian.PutUint64(b, cfg.PkgABIRevision)

	path := filepath.Join(abiDir, "abi-revision")
	if err := ioutil.WriteFile(path, b, os.ModePerm); err != nil {
		return err
	}

	manifest.Paths[abiRevisionKey] = path

	return nil
}

// ErrRequiredFileMissing is returned by operations when the operation depends
// on a file that was not found on disk.
type ErrRequiredFileMissing struct {
	Path string
}

func (e ErrRequiredFileMissing) Error() string {
	return fmt.Sprintf("pkg: missing required file: %q", e.Path)
}

// RequiredFiles is a list of files that are required before a package can be sealed.
var RequiredFiles = []string{"meta/contents", "meta/package"}

// Validate ensures that the package contains the required files.
func Validate(cfg *Config) error {
	manifest, err := cfg.Manifest()
	if err != nil {
		return err
	}
	meta := manifest.Meta()

	for _, f := range RequiredFiles {
		if _, ok := meta[f]; !ok {
			return ErrRequiredFileMissing{f}
		}
	}

	return nil
}

// Seal archives meta/ into a FAR archive named meta.far.
func Seal(cfg *Config) (string, error) {
	manifest, err := cfg.Manifest()
	if err != nil {
		return "", err
	}

	if err := Validate(cfg); err != nil {
		return "", err
	}

	archive, err := os.Create(cfg.MetaFAR())
	if err != nil {
		return "", err
	}

	if err := far.Write(archive, manifest.Meta()); err != nil {
		return "", err
	}

	if _, err := archive.Seek(0, io.SeekStart); err != nil {
		return "", err
	}

	var tree merkle.Tree
	if _, err := tree.ReadFrom(archive); err != nil {
		return "", err
	}
	if err := ioutil.WriteFile(cfg.MetaFARMerkle(), []byte(fmt.Sprintf("%x", tree.Root())), os.ModePerm); err != nil {
		return "", err
	}
	return cfg.MetaFAR(), archive.Close()
}
