// Copyright 2023 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 common

import (
	"encoding/json"
	"fmt"
	"os/exec"
	"path/filepath"
	"time"

	"dawn.googlesource.com/dawn/tools/src/oswrapper"

	"dawn.googlesource.com/dawn/tools/src/fileutils"
)

type Builder struct {
	Name string // 'standalone', 'node'
	Out  string // Absolute path to the output directory
	CTS  string // Absolute path to the CTS root directory
	npx  string // Path to the npx executable
}

// BuildIfRequired calls Build() if the CTS sources have been modified since the last build.
func (b *Builder) BuildIfRequired(verbose bool, osWrapper oswrapper.OSWrapper) error {
	name := fmt.Sprintf("cts %v", b.Name)

	// Scan the CTS source to determine the most recent change to the CTS source
	mostRecentSourceChange, err := scanSourceTimestamps(filepath.Join(b.Out, "../src"), verbose)
	if err != nil {
		return fmt.Errorf("failed to scan source files for modified timestamps: %w", err)
	}

	type Cache struct {
		BuildTimestamp map[string]time.Time // name -> most recent timestamp
	}
	cache := Cache{BuildTimestamp: map[string]time.Time{}}

	cachePath := ""
	if home, err := osWrapper.UserHomeDir(); err == nil {
		cacheDir := filepath.Join(home, ".cache/webgpu")
		cachePath = filepath.Join(cacheDir, "run-cts.cjson")
		osWrapper.MkdirAll(cacheDir, 0777)
	}

	needsRebuild := true
	if cachePath != "" { // consult the cache to see if we need to rebuild
		if cacheFile, err := osWrapper.Open(cachePath); err == nil {
			if err := json.NewDecoder(cacheFile).Decode(&cache); err == nil {
				if fileutils.IsDir(b.Out, osWrapper) {
					needsRebuild = mostRecentSourceChange.After(cache.BuildTimestamp[b.Name])
				}
			}
			cacheFile.Close()
		}
	}

	if verbose {
		fmt.Println(name, "needs rebuild:", needsRebuild)
	}

	if needsRebuild {
		if err := b.Build(verbose, osWrapper); err != nil {
			return fmt.Errorf("failed to build %v: %w", name, err)
		}
	}

	if cachePath != "" {
		// Update the cache timestamp
		if cacheFile, err := osWrapper.Create(cachePath); err == nil {
			cache.BuildTimestamp[b.Name] = mostRecentSourceChange
			json.NewEncoder(cacheFile).Encode(&cache)
			cacheFile.Close()
		}
	}

	return nil
}

// Build executes the necessary build commands to build the CTS, including
// copying the cache files from gen to the out directory and compiling the
// TypeScript files down to JavaScript.
func (b *Builder) Build(verbose bool, fsReaderWrapper oswrapper.FilesystemReaderWriter) error {
	if verbose {
		start := time.Now()
		fmt.Printf("Building CTS %v...\n", b.Name)
		defer func() {
			fmt.Println("completed in", time.Since(start))
		}()
	}

	if err := fsReaderWrapper.MkdirAll(b.Out, 0777); err != nil {
		return err
	}

	if !fileutils.IsExe(b.npx, fsReaderWrapper) {
		return fmt.Errorf("cannot find npx at '%v'", b.npx)
	}

	for _, action := range []string{"run:generate-version", b.Name} {
		cmd := exec.Command(b.npx, "grunt", action)
		cmd.Dir = b.CTS
		out, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("%w: %v", err, string(out))
		}
		if verbose {
			fmt.Println(string(out))
		}
	}

	return nil
}
