// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Provides service implementations and management
package services

import (
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"

	"github.com/golang/protobuf/jsonpb"
	buildapi "go.chromium.org/chromiumos/config/go/build/api"
	"go.chromium.org/chromiumos/config/go/test/api"
)

const (
	_LOGIN_USERNAME       = "oauth2accesstoken"
	_LOGIN_PASSWORD       = "$(gcloud auth print-access-token)"
	_LOGIN_REGISTRY       = "us-docker.pkg.dev"
	IMAGE_DATA_TEMPLATE   = "gs://chromeos-image-archive/%s-release/%s*/metadata/containers.jsonpb"
	CROS_TOOL_RUNNER_PATH = "chromiumos/infra/cros-tool-runner/${platform}"
)

type ctrServiceCommands struct {
	LoginRegistry  ServiceCommand_
	StartContainer ServiceCommand_
}

// Enum of available commands for cros-tool-runner
func CTR_SERVICE_COMMANDS() ctrServiceCommands {
	return ctrServiceCommands{
		LoginRegistry:  "login_registry",
		StartContainer: "start_container",
	}
}

// Service implementation for cros-tool-runner
type CTRService struct {
	Service
	ServiceBase

	client api.CrosToolRunnerContainerServiceClient
}

func (c *CTRService) Start() error {
	c.EnsurePort()

	c.LocalLogger.Printf("Starting %s on port %d", c.Name, c.Port)

	starter := &SetupCTR{
		ctr: c,
	}

	if err := c.executor.Start(starter); err != nil {
		return err
	}

	// Start CacheServer, SSHTunnel, SSHReverseTunnel, CrosDut
	if c.manager.DutHost != "" {
		cacheServerService := &CacheServerService{
			ServiceBase: NewServiceBase(
				c.manager,
				c.executor,
				SERVICES().CacheServer,
			),
		}
		sshReverseTunnelService := &SSHTunnelService{
			ServiceBase: NewServiceBase(
				c.manager,
				c.executor,
				SERVICES().SSHReverseTunnel,
			),
		}
		sshTunnelService := &SSHTunnelService{
			ServiceBase: NewServiceBase(
				c.manager,
				c.executor,
				SERVICES().SSHTunnel,
			),
		}
		crosDutService := &CrosDutService{
			ServiceBase: NewServiceBase(
				c.manager,
				c.executor,
				SERVICES().CrosDut,
			),
		}

		if err := c.manager.Start(cacheServerService.Name, cacheServerService); err != nil {
			return err
		}
		if err := c.manager.Start(sshReverseTunnelService.Name, sshReverseTunnelService); err != nil {
			return err
		}
		if err := c.manager.Start(sshTunnelService.Name, sshTunnelService); err != nil {
			return err
		}
		if err := c.manager.Start(crosDutService.Name, crosDutService); err != nil {
			return err
		}
	}

	return nil
}

func (c *CTRService) Execute(commandName ServiceCommand_, args ...interface{}) error {
	var cmd ServiceCommand = nil
	switch commandName {
	case CTR_SERVICE_COMMANDS().LoginRegistry:
		cmd = &LoginRegistryCommand{
			ctr: c,
			request: &api.LoginRegistryRequest{
				Username: _LOGIN_USERNAME,
				Password: _LOGIN_PASSWORD,
				Registry: _LOGIN_REGISTRY,
			},
		}
	case CTR_SERVICE_COMMANDS().StartContainer:
		startContainerRequest := args[0].([]interface{})[0].(*api.StartContainerRequest)

		cmd = &StartContainerCommand{
			ctr:     c,
			request: startContainerRequest,
		}
	default:
		return fmt.Errorf("Command %s not found", commandName)
	}
	return c.executor.Execute(cmd)
}

func (c *CTRService) Stop() error {
	stopper := &StopCTR{
		ctr: c,
	}
	return c.executor.Stop(stopper)
}

// Setup

type SetupCTR struct {
	ServiceSetup
	ctr *CTRService
}

func (starter *SetupCTR) Setup() error {
	path, err := starter.fetchCrosToolRunner()
	if err != nil {
		return err
	}

	go BuildServiceListener(
		&starter.ctr.ServiceBase,
		false,
		exec.Command(fmt.Sprintf("%s/cros-tool-runner", path), "serve", "-port", fmt.Sprint(starter.ctr.Port)),
	)()

	if err := <-starter.ctr.ReadyChan; err != nil {
		return err
	}

	if err := BuildConnection(&starter.ctr.ServiceBase); err != nil {
		return err
	}
	starter.ctr.client = api.NewCrosToolRunnerContainerServiceClient(starter.ctr.conn)

	if err := starter.ctr.manager.Execute(SERVICES().CrosToolRunner, CTR_SERVICE_COMMANDS().LoginRegistry); err != nil {
		return err
	}

	if err := starter.fetchImageData(); err != nil {
		return fmt.Errorf("could not fetch image data, %s", err)
	}

	return nil
}

func (starter *SetupCTR) fetchCrosToolRunner() (string, error) {
	dir := fmt.Sprintf("%s/bin/", starter.ctr.BaseDir)

	if err := os.RemoveAll(dir); err != nil {
		return "", fmt.Errorf("Failed to remove previous binaries, %s", err)
	}

	if err := os.MkdirAll(dir, 0755); err != nil {
		starter.ctr.LocalLogger.Printf("Failed to create local-cft binaries directory, %s\n", err)
	}
	if _, err := exec.Command("cipd", "init", dir).Output(); err != nil {
		return "", fmt.Errorf("Could not run 'cipd init', %s", err)
	}
	if _, err := exec.Command("cipd", "install", CROS_TOOL_RUNNER_PATH, "prod", "-root", dir).Output(); err != nil {
		return "", fmt.Errorf("Failed to install cros-tool-runner, %s", err)
	}

	return dir, nil
}

func (starter *SetupCTR) fetchImageData() error {
	if strings.HasPrefix(starter.ctr.manager.Build, "LATEST") {
		latest := exec.Command("gsutil", "cat", fmt.Sprintf("gs://chromeos-image-archive/%s-release/%s",
			starter.ctr.manager.Board,
			starter.ctr.manager.Build,
		))

		latestOut, err := latest.Output()
		if err != nil {
			return err
		}
		starter.ctr.manager.Build = string(latestOut)
	}
	template := fmt.Sprintf(
		IMAGE_DATA_TEMPLATE,
		starter.ctr.manager.Board,
		starter.ctr.manager.Build,
	)

	gsutil := exec.Command("gsutil", "ls", "-l", template)
	sort := exec.Command("sort", "-k", "2")

	gPipe, err := gsutil.StdoutPipe()
	if err != nil {
		return err
	}

	sort.Stdin = gPipe

	if err := gsutil.Start(); err != nil {
		return err
	}
	imageDataRaw, err := sort.Output()
	if err != nil {
		return err
	}

	regContainerEx := regexp.MustCompile(`gs://.*.jsonpb`)
	containerImages := regContainerEx.FindAllStringSubmatch(string(imageDataRaw), -1)

	if len(containerImages) == 0 {
		return fmt.Errorf("Could not find any container images with given build number %s", starter.ctr.manager.Build)
	}
	archivePath := containerImages[len(containerImages)-1][0]
	starter.ctr.manager.imagePath = strings.Split(archivePath, "metadata")[0] // Add to Manager

	cat := exec.Command("gsutil", "cat", archivePath)

	catOut, err := cat.Output()
	if err != nil {
		return err
	}

	reader := strings.NewReader(string(catOut))

	metadata := &buildapi.ContainerMetadata{}
	unmarshaler := jsonpb.Unmarshaler{}
	unmarshaler.Unmarshal(reader, metadata)
	starter.ctr.manager.images = metadata.Containers[starter.ctr.manager.Board].Images // Add to Manager

	return nil
}

// Stopper

type StopCTR struct {
	ServiceStopper
	ctr *CTRService
}

func (stopper *StopCTR) Stop() error {
	if stopper.ctr.conn != nil {
		stopper.ctr.conn.Close()
	}

	if stopper.ctr.Started {
		stopper.ctr.CloseChan <- struct{}{}
		<-stopper.ctr.CloseFinishedChan
	}

	WriteLogs(&stopper.ctr.ServiceBase)

	return nil
}

// Commands

type LoginRegistryCommand struct {
	ServiceCommand
	ctr     *CTRService
	request *api.LoginRegistryRequest
}

func (cmd *LoginRegistryCommand) Execute() error {
	_, err := cmd.ctr.client.LoginRegistry(cmd.ctr.manager.ctx, cmd.request)
	return err
}

type StartContainerCommand struct {
	ServiceCommand
	ctr     *CTRService
	request *api.StartContainerRequest
}

func (cmd *StartContainerCommand) Execute() error {
	_, err := cmd.ctr.client.StartContainer(cmd.ctr.manager.ctx, cmd.request)
	return err
}
