// 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 (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"

	versionHistory "go.fuchsia.dev/fuchsia/src/lib/versioning/version-history/go"
	"go.fuchsia.dev/fuchsia/src/sys/pkg/lib/merkle"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/pkg"
)

// Config contains global build configuration for other build commands
type Config struct {
	OutputDir       string
	ManifestPath    string
	KeyPath         string
	TempDir         string
	PkgName         string
	PkgRepository   string
	PkgVersion      string
	PkgABIRevision  uint64
	SubpackagesPath string

	// the manifest is memoized lazily, on the first call to Manifest()
	manifest *Manifest
}

// NewConfig initializes a new configuration with conventional defaults
func NewConfig() *Config {
	cfg := &Config{
		OutputDir:       ".",
		ManifestPath:    ".",
		KeyPath:         "",
		TempDir:         os.TempDir(),
		PkgName:         "",
		PkgRepository:   "",
		PkgVersion:      "0",
		SubpackagesPath: "",
		PkgABIRevision:  0,
	}
	return cfg
}

// TestConfig produces a configuration suitable for testing. It creates a
// temporary directory as a parent of the returned config.OutputDir and
// config.TempDir. Callers should remove this directory.
func TestConfig() *Config {
	d, err := os.MkdirTemp("", "pm-test")
	if err != nil {
		panic(err)
	}
	cfg := &Config{
		OutputDir:       filepath.Join(d, "output"),
		ManifestPath:    filepath.Join(d, "manifest"),
		KeyPath:         filepath.Join(d, "key"),
		TempDir:         filepath.Join(d, "tmp"),
		PkgName:         "testpackage",
		PkgRepository:   "testrepository.com",
		PkgVersion:      "0",
		SubpackagesPath: "",
		PkgABIRevision:  TestABIRevision,
	}
	for _, d := range []string{cfg.OutputDir, cfg.TempDir} {
		os.MkdirAll(d, os.ModePerm)
	}
	return cfg
}

// InitFlags adds flags to a flagset for altering Config defaults
func (c *Config) InitFlags(fs *flag.FlagSet) {
	fs.StringVar(&c.OutputDir, "o", c.OutputDir, "archive output directory")
	fs.StringVar(&c.ManifestPath, "m", c.ManifestPath, "build manifest (or package directory)")
	fs.StringVar(&c.KeyPath, "k", c.KeyPath, "deprecated; do not use")
	fs.StringVar(&c.TempDir, "t", c.TempDir, "temporary directory")
	fs.StringVar(&c.PkgName, "n", c.PkgName, "name of the packages")
	fs.StringVar(&c.PkgRepository, "r", c.PkgRepository, "repository of the packages")
	fs.StringVar(&c.SubpackagesPath, "subpackages", c.SubpackagesPath, "metafile of subpackages")
	fs.Func("api-level", "package API level", func(value string) error {
		apiLevel, err := strconv.ParseUint(value, 0, 64)
		if err != nil {
			return err
		}

		c.PkgABIRevision, err = versionHistory.History().CheckApiLevelForBuild(apiLevel)
		return err
	})
}

// Manifest initializes and returns the configured manifest. The manifest may be
// modified during the build process to add/remove files.
func (c *Config) Manifest() (*Manifest, error) {
	var err error
	if c.manifest == nil {
		sources := []string{}

		if c.ManifestPath != "" {
			sources = append(sources, c.ManifestPath)
		}

		// Only use outputdir as a source if no manifest was supplied.
		if c.ManifestPath == "" && c.OutputDir != "" {
			sources = append(sources, c.OutputDir)
		}

		if len(sources) == 0 {
			err = os.ErrNotExist
		}
		c.manifest, err = NewManifest(sources)
	}
	return c.manifest, err
}

// MetaFAR returns the path to the meta.far that build.Seal generates
func (c *Config) MetaFAR() string {
	return filepath.Join(c.OutputDir, "meta.far")
}

func (c *Config) Package() (pkg.Package, error) {
	p := pkg.Package{
		Name:    c.PkgName,
		Version: c.PkgVersion,
	}

	if p.Name == "" {
		p.Name = filepath.Base(c.OutputDir)
		if p.Name == "." {
			var err error
			p.Name, err = filepath.Abs(p.Name)
			if err != nil {
				return p, fmt.Errorf("build: unable to compute package name from directory: %s", err)
			}
			p.Name = filepath.Base(p.Name)
		}
	}

	return p, nil
}

func (c *Config) BlobInfo() ([]PackageBlobInfo, error) {
	manifest, err := c.Manifest()
	if err != nil {
		return nil, err
	}

	var result []PackageBlobInfo

	// Include a meta FAR entry first. If blobs.sizes becomes the new root
	// blob for a package, targets need to know which unnamed blob is the
	// meta FAR.
	{
		archive, err := os.Open(c.MetaFAR())
		if err != nil {
			return nil, err
		}
		var tree merkle.Tree
		if _, err := tree.ReadFrom(archive); err != nil {
			return nil, err
		}
		var merkle MerkleRoot
		copy(merkle[:], tree.Root()[:32])

		info, err := os.Stat(c.MetaFAR())
		if err != nil {
			return nil, err
		}

		result = append(result, PackageBlobInfo{
			SourcePath: c.MetaFAR(),
			Path:       "meta/",
			Merkle:     merkle,
			Size:       uint64(info.Size()),
		})
	}

	contentsPath := filepath.Join(c.OutputDir, "meta", "contents")
	contents, err := LoadMetaContents(contentsPath)
	if err != nil {
		return nil, err
	}

	contentsKeys := make([]string, 0, len(contents))
	for k := range contents {
		contentsKeys = append(contentsKeys, k)
	}
	sort.Strings(contentsKeys)

	for _, path := range contentsKeys {
		merkle := contents[path]
		info, err := os.Stat(manifest.Paths[path])
		if err != nil {
			return nil, err
		}

		result = append(result, PackageBlobInfo{
			SourcePath: manifest.Paths[path],
			Path:       path,
			Merkle:     merkle,
			Size:       uint64(info.Size()),
		})
	}

	return result, nil
}

func (c *Config) OutputManifest() (*PackageManifest, error) {
	p, err := c.Package()
	if err != nil {
		return nil, err
	}
	blobs, err := c.BlobInfo()
	if err != nil {
		return nil, err
	}
	return &PackageManifest{
		Version:    "1",
		Repository: c.PkgRepository,
		Package:    p,
		Blobs:      blobs,
	}, err
}
