// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Package install installs the tintd vscode extension for local development
// via a symlink to the build directory
package install

import (
	"bytes"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	"dawn.googlesource.com/dawn/tools/src/cmd/tintd/common"
	"dawn.googlesource.com/dawn/tools/src/fileutils"
)

func init() {
	common.Register(&Cmd{})
}

type Cmd struct {
	flags struct {
		buildDir string
		npmPath  string
	}
}

func (Cmd) Name() string {
	return "install"
}

func (Cmd) Desc() string {
	return `install installs the tintd vscode extension for local development via a symlink to the build directory`
}

func (c *Cmd) RegisterFlags(ctx context.Context, _ any) ([]string, error) {
	dawnRoot := fileutils.DawnRoot()
	npmPath, _ := exec.LookPath("npm")
	flag.StringVar(&c.flags.buildDir, "build", filepath.Join(dawnRoot, "out", "active"), "the output build directory")
	flag.StringVar(&c.flags.npmPath, "npm", npmPath, "path to npm")

	return nil, nil
}

func (c Cmd) Run(ctx context.Context, _ any) error {
	pkgDir := c.findPackage()
	if pkgDir == "" {
		return fmt.Errorf("could not find extension package directory at '%v'", c.flags.buildDir)
	}

	if !fileutils.IsExe(c.flags.npmPath) {
		return fmt.Errorf("could not find npm")
	}

	// Build the package
	npmCmd := exec.Command(c.flags.npmPath, "install")
	npmCmd.Dir = pkgDir
	if out, err := npmCmd.CombinedOutput(); err != nil {
		return fmt.Errorf("npm install failed:\n%v\n%v", err, string(out))
	}

	// Load the package to get the name and version
	pkg := struct {
		Name    string
		Version string
	}{}
	packageJSONPath := filepath.Join(pkgDir, "package.json")
	packageJSON, err := os.ReadFile(packageJSONPath)
	if err != nil {
		return fmt.Errorf("could not open '%v'", packageJSONPath)
	}
	if err := json.NewDecoder(bytes.NewReader(packageJSON)).Decode(&pkg); err != nil {
		return fmt.Errorf("could not parse '%v': %v", packageJSONPath, err)
	}

	// Symlink to vscode extensions directory
	home, err := os.UserHomeDir()
	if err != nil {
		return fmt.Errorf("failed to obtain home directory: %w", err)
	}
	vscodeBaseExtsDir := filepath.Join(home, ".vscode", "extensions")
	if !fileutils.IsDir(vscodeBaseExtsDir) {
		return fmt.Errorf("vscode extensions directory not found at '%v'", vscodeBaseExtsDir)
	}

	vscodeTintdDir := filepath.Join(vscodeBaseExtsDir, fmt.Sprintf("google.%v-%v", pkg.Name, pkg.Version))
	os.RemoveAll(vscodeTintdDir)

	if err := os.Symlink(pkgDir, vscodeTintdDir); err != nil {
		return fmt.Errorf("failed to create symlink '%v' <- '%v': %w", pkgDir, vscodeTintdDir, err)
	}

	return nil
}

// findPackage looks for and returns the tintd package directory. Returns an empty string if not found.
func (c Cmd) findPackage() string {
	searchPaths := []string{
		filepath.Join(c.flags.buildDir, "gen/vscode"),
		c.flags.buildDir,
	}
	files := []string{"tintd", "package.json"}

nextDir:
	for _, dir := range searchPaths {
		for _, file := range files {
			if !fileutils.IsFile(filepath.Join(dir, file)) {
				continue nextDir
			}
		}
		return dir
	}

	return "" // Not found
}
