// Copyright 2023 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bazel

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"net"
	os_lib "os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

// Logs fatal events of ProxyServer.
type ServerLogger interface {
	Fatal(v ...interface{})
	Fatalf(format string, v ...interface{})
}

// CmdRequest is a request to the Bazel Proxy server.
type CmdRequest struct {
	// Args to the Bazel command.
	Argv []string
	// Environment variables to pass to the Bazel invocation. Strings should be of
	// the form "KEY=VALUE".
	Env []string
}

// CmdResponse is a response from the Bazel Proxy server.
type CmdResponse struct {
	Stdout      string
	Stderr      string
	ErrorString string
}

// ProxyClient is a client which can issue Bazel commands to the Bazel
// proxy server. Requests are issued (and responses received) via a unix socket.
// See ProxyServer for more details.
type ProxyClient struct {
	outDir string
}

// ProxyServer is a server which runs as a background goroutine. Each
// request to the server describes a Bazel command which the server should run.
// The server then issues the Bazel command, and returns a response describing
// the stdout/stderr of the command.
// Client-server communication is done via a unix socket under the output
// directory.
// The server is intended to circumvent sandboxing for subprocesses of the
// build. The build orchestrator (soong_ui) can launch a server to exist outside
// of sandboxing, and sandboxed processes (such as soong_build) can issue
// bazel commands through this socket tunnel. This allows a sandboxed process
// to issue bazel requests to a bazel that resides outside of sandbox. This
// is particularly useful to maintain a persistent Bazel server which lives
// past the duration of a single build.
// The ProxyServer will only live as long as soong_ui does; the
// underlying Bazel server will live past the duration of the build.
type ProxyServer struct {
	logger       ServerLogger
	outDir       string
	workspaceDir string
	// The server goroutine will listen on this channel and stop handling requests
	// once it is written to.
	done chan struct{}
}

// NewProxyClient is a constructor for a ProxyClient.
func NewProxyClient(outDir string) *ProxyClient {
	return &ProxyClient{
		outDir: outDir,
	}
}

func unixSocketPath(outDir string) string {
	return filepath.Join(outDir, "bazelsocket.sock")
}

// IssueCommand issues a request to the Bazel Proxy Server to issue a Bazel
// request. Returns a response describing the output from the Bazel process
// (if the Bazel process had an error, then the response will include an error).
// Returns an error if there was an issue with the connection to the Bazel Proxy
// server.
func (b *ProxyClient) IssueCommand(req CmdRequest) (CmdResponse, error) {
	var resp CmdResponse
	var err error
	// Check for connections every 1 second. This is chosen to be a relatively
	// short timeout, because the proxy server should accept requests quite
	// quickly.
	d := net.Dialer{Timeout: 1 * time.Second}
	var conn net.Conn
	conn, err = d.Dial("unix", unixSocketPath(b.outDir))
	if err != nil {
		return resp, err
	}
	defer conn.Close()

	enc := gob.NewEncoder(conn)
	if err = enc.Encode(req); err != nil {
		return resp, err
	}
	dec := gob.NewDecoder(conn)
	err = dec.Decode(&resp)
	return resp, err
}

// NewProxyServer is a constructor for a ProxyServer.
func NewProxyServer(logger ServerLogger, outDir string, workspaceDir string) *ProxyServer {
	return &ProxyServer{
		logger:       logger,
		outDir:       outDir,
		workspaceDir: workspaceDir,
		done:         make(chan struct{}),
	}
}

func ExecBazel(bazelPath string, workspaceDir string, request CmdRequest) (stdout []byte, stderr []byte, cmdErr error) {
	bazelCmd := exec.Command(bazelPath, request.Argv...)
	bazelCmd.Dir = workspaceDir
	bazelCmd.Env = request.Env

	stderrBuffer := &bytes.Buffer{}
	bazelCmd.Stderr = stderrBuffer

	if output, err := bazelCmd.Output(); err != nil {
		cmdErr = fmt.Errorf("bazel command failed: %s\n---command---\n%s\n---env---\n%s\n---stderr---\n%s---",
			err, bazelCmd, strings.Join(bazelCmd.Env, "\n"), stderrBuffer)
	} else {
		stdout = output
	}
	stderr = stderrBuffer.Bytes()
	return
}

func (b *ProxyServer) handleRequest(conn net.Conn) error {
	defer conn.Close()

	dec := gob.NewDecoder(conn)
	var req CmdRequest
	if err := dec.Decode(&req); err != nil {
		return fmt.Errorf("Error decoding request: %s", err)
	}

	stdout, stderr, cmdErr := ExecBazel("./build/bazel/bin/bazel", b.workspaceDir, req)
	errorString := ""
	if cmdErr != nil {
		errorString = cmdErr.Error()
	}

	resp := CmdResponse{string(stdout), string(stderr), errorString}
	enc := gob.NewEncoder(conn)
	if err := enc.Encode(&resp); err != nil {
		return fmt.Errorf("Error encoding response: %s", err)
	}
	return nil
}

func (b *ProxyServer) listenUntilClosed(listener net.Listener) error {
	for {
		// Check for connections every 1 second. This is a blocking operation, so
		// if the server is closed, the goroutine will not fully close until this
		// deadline is reached. Thus, this deadline is short (but not too short
		// so that the routine churns).
		listener.(*net.UnixListener).SetDeadline(time.Now().Add(time.Second))
		conn, err := listener.Accept()

		select {
		case <-b.done:
			return nil
		default:
		}

		if err != nil {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				// Timeout is normal and expected while waiting for client to establish
				// a connection.
				continue
			} else {
				b.logger.Fatalf("Listener error: %s", err)
			}
		}

		err = b.handleRequest(conn)
		if err != nil {
			b.logger.Fatal(err)
		}
	}
}

// Start initializes the server unix socket and (in a separate goroutine)
// handles requests on the socket until the server is closed. Returns an error
// if a failure occurs during initialization. Will log any post-initialization
// errors to the server's logger.
func (b *ProxyServer) Start() error {
	unixSocketAddr := unixSocketPath(b.outDir)
	if err := os_lib.RemoveAll(unixSocketAddr); err != nil {
		return fmt.Errorf("couldn't remove socket '%s': %s", unixSocketAddr, err)
	}
	listener, err := net.Listen("unix", unixSocketAddr)

	if err != nil {
		return fmt.Errorf("error listening on socket '%s': %s", unixSocketAddr, err)
	}

	go b.listenUntilClosed(listener)
	return nil
}

// Close shuts down the server. This will stop the server from listening for
// additional requests.
func (b *ProxyServer) Close() {
	b.done <- struct{}{}
}
