// Copyright 2020 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 cli

import (
	"context"
	"flag"
	"fmt"
	"log"
	"path/filepath"
	"time"

	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/artifacts"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/avb"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/device"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/omaha_tool"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/updater"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/util"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/zbi"
)

type InstallerMode = string

const (
	// Install OTAs with the omaha-client.
	Omaha = "omaha"

	// Install OTAs with the system-update-checker.
	SystemUpdateChecker = "system-update-checker"

	// Install OTAs directly with the system-updater.
	SystemUpdater = "system-updater"
)

type InstallerConfig struct {
	installerMode               InstallerMode
	avbToolPath                 string
	zbiToolPath                 string
	keyPath                     string
	keyMetadataPath             string
	avbTool                     *avb.AVBTool
	zbiTool                     *zbi.ZBITool
	updater                     updater.Updater
	omahaTool                   *omaha_tool.OmahaTool
	omahaToolPath               string
	privateKeyId                string
	privateKeyPath              string
	omahaAddress                string
	omahaRequireCup             bool
	workaroundOtaNoRewriteRules bool
	testDataPath                string
}

func NewInstallerConfig(fs *flag.FlagSet, testDataPath string) (*InstallerConfig, error) {
	c := &InstallerConfig{}

	c.testDataPath = testDataPath
	fs.StringVar(&c.avbToolPath, "avbtool-path", filepath.Join(testDataPath, "avbtool.py"), "path to the avbtool binary")
	fs.StringVar(&c.installerMode, "installer", SystemUpdateChecker, "the installation mode (default: system-update-checker)")
	fs.StringVar(&c.keyMetadataPath, "vbmeta-key-metadata", "", "path to the vbmeta public key metadata")
	fs.StringVar(&c.keyPath, "vbmeta-key", "", "path to the vbmeta private key")
	fs.StringVar(&c.omahaAddress, "omaha-address", ":0", "which address to serve omaha server on (default random)")
	fs.StringVar(&c.omahaToolPath, "omaha-tool-path", filepath.Join(testDataPath, "mock-omaha-server"), "the path of the mock-omaha-server binary to invoke.")
	// This must match the key_id in
	// src/sys/pkg/bin/omaha-client:empty_eager_package_config, which relies
	// on src/sys/pkg/bin/omaha-client/test_data/key_config.json.
	fs.StringVar(&c.privateKeyId, "omaha-key-id", "123456789", "the integer private key ID to use for CUP within Omaha requests.")
	fs.StringVar(&c.privateKeyPath, "omaha-key-path", filepath.Join(testDataPath, "test_private_key.pem"), "the path of the private key .pem to use for CUP within Omaha requests.")
	fs.StringVar(&c.zbiToolPath, "zbitool-path", filepath.Join(testDataPath, "zbi"), "path to the zbi binary")
	fs.BoolVar(&c.omahaRequireCup, "require-cup", false, "if true, mock-omaha-server will assert that all incoming requests have CUP enabled.")
	fs.BoolVar(&c.workaroundOtaNoRewriteRules, "workaround-downgrade-ota-no-rewrite-rules", false, "if true, omaha updater will not set workaround downgrade ota rewrite rules.")

	return c, nil
}

func (c *InstallerConfig) Validate() error {
	for _, s := range []string{
		c.avbToolPath,
		c.keyMetadataPath,
		c.keyPath,
		c.omahaToolPath,
		c.privateKeyPath,
		c.zbiToolPath,
	} {
		if err := util.ValidatePath(s); err != nil {
			return err
		}
	}
	return nil
}

func (c *InstallerConfig) AVBTool() (*avb.AVBTool, error) {
	if c.avbTool == nil {
		if c.keyPath == "" {
			c.keyPath = filepath.Join(c.testDataPath, "atx_psk.pem")
		}
		if c.keyMetadataPath == "" {
			c.keyMetadataPath = filepath.Join(c.testDataPath, "avb_atx_metadata.bin")
		}

		avbTool, err := avb.NewAVBTool(c.avbToolPath, c.keyPath, c.keyMetadataPath)
		if err != nil {
			return nil, err
		}
		c.avbTool = avbTool
	}

	return c.avbTool, nil
}

func (c *InstallerConfig) ZBITool() (*zbi.ZBITool, error) {
	if c.zbiTool == nil {
		zbiTool, err := zbi.NewZBITool(c.zbiToolPath)
		if err != nil {
			return nil, err
		}
		c.zbiTool = zbiTool
	}

	return c.zbiTool, nil
}

func (c *InstallerConfig) OmahaTool(ctx context.Context, device *device.Client) (*omaha_tool.OmahaTool, error) {
	localHostname, err := device.GetSSHConnection(ctx)
	if err != nil {
		return nil, err
	}
	omahaTool, err := omaha_tool.NewOmahaServer(ctx, omaha_tool.OmahaToolArgs{
		ToolPath:       c.omahaToolPath,
		PrivateKeyId:   c.privateKeyId,
		PrivateKeyPath: c.privateKeyPath,
		AppId:          "e2e-ota-test-app-id",
		LocalHostname:  localHostname,
		RequireCup:     c.omahaRequireCup,
	}, /*stdout=*/ nil /*stderr=*/, nil)
	if err != nil {
		return nil, err
	}
	return omahaTool, nil
}

func (c *InstallerConfig) NeedsInitialization() bool {
	// The omaha-client needs the device to be flashed or paved since the
	// tests start a fake omaha server and inject's the address into a
	// custom vbmeta.
	return c.installerMode == Omaha
}

// ConfigureBuild configures a build for the updater.
func (c *InstallerConfig) ConfigureBuild(ctx context.Context, device *device.Client, build artifacts.Build) (artifacts.Build, error) {
	switch c.installerMode {
	case Omaha:
		if c.omahaTool == nil {
			omahaTool, err := c.OmahaTool(ctx, device)
			if err != nil {
				return nil, err
			}
			c.omahaTool = omahaTool
		}

		avbTool, err := c.AVBTool()
		if err != nil {
			return nil, err
		}

		zbiTool, err := c.ZBITool()
		if err != nil {
			return nil, err
		}

		return artifacts.NewOmahaBuild(build, c.omahaTool, avbTool, zbiTool), nil

	case SystemUpdateChecker:
		return build, nil

	case SystemUpdater:
		return build, nil

	default:
		return nil, fmt.Errorf("Invalid installer mode %v", c.installerMode)
	}
}

// Updater returns the configured updater.
func (c *InstallerConfig) Updater(checkForUnkownFirmware bool) (updater.Updater, error) {
	switch c.installerMode {
	case Omaha:
		avbTool, err := c.AVBTool()
		if err != nil {
			return nil, err
		}

		zbiTool, err := c.ZBITool()
		if err != nil {
			return nil, err
		}

		return updater.NewOmahaUpdater(
			c.omahaTool,
			avbTool,
			zbiTool,
			c.workaroundOtaNoRewriteRules,
			checkForUnkownFirmware,
		), nil

	case SystemUpdateChecker:
		return updater.NewSystemUpdateChecker(
			checkForUnkownFirmware,
		), nil

	case SystemUpdater:
		return updater.NewSystemUpdater(checkForUnkownFirmware), nil

	default:
		return nil, fmt.Errorf("Invalid installer mode: %v", c.installerMode)
	}
}

func (c *InstallerConfig) Shutdown(ctx context.Context) {
	if c.omahaTool == nil {
		return
	}
	ch := make(chan error)
	go func() {
		ch <- c.omahaTool.Shutdown(ctx)
	}()

	select {
	case err := <-ch:
		if err != nil {
			log.Printf("caught an error: %w", err)
		}
	case <-time.After(5 * time.Second):
		log.Printf("took longer than 5 seconds to shut down the installer")
	}
}
