// Copyright 2017 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 build

import (
	"compress/gzip"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

func absPath(ctx Context, p string) string {
	ret, err := filepath.Abs(p)
	if err != nil {
		ctx.Fatalf("Failed to get absolute path: %v", err)
	}
	return ret
}

// indexList finds the index of a string in a []string
func indexList(s string, list []string) int {
	for i, l := range list {
		if l == s {
			return i
		}
	}

	return -1
}

// inList determines whether a string is in a []string
func inList(s string, list []string) bool {
	return indexList(s, list) != -1
}

// removeFromlist removes all occurrences of the string in list.
func removeFromList(s string, list []string) []string {
	filteredList := make([]string, 0, len(list))
	for _, ls := range list {
		if s != ls {
			filteredList = append(filteredList, ls)
		}
	}
	return filteredList
}

// ensureDirectoriesExist is a shortcut to os.MkdirAll, sending errors to the ctx logger.
func ensureDirectoriesExist(ctx Context, dirs ...string) {
	for _, dir := range dirs {
		err := os.MkdirAll(dir, 0777)
		if err != nil {
			ctx.Fatalf("Error creating %s: %q\n", dir, err)
		}
	}
}

// ensureEmptyDirectoriesExist ensures that the given directories exist and are empty
func ensureEmptyDirectoriesExist(ctx Context, dirs ...string) {
	// remove all the directories
	for _, dir := range dirs {
		seenErr := map[string]bool{}
		for {
			err := os.RemoveAll(dir)
			if err == nil {
				break
			}

			if pathErr, ok := err.(*os.PathError); !ok ||
				dir == pathErr.Path || seenErr[pathErr.Path] {

				ctx.Fatalf("Error removing %s: %q\n", dir, err)
			} else {
				seenErr[pathErr.Path] = true
				err = os.Chmod(filepath.Dir(pathErr.Path), 0700)
				if err != nil {
					ctx.Fatal(err)
				}
			}
		}
	}
	// recreate all the directories
	ensureDirectoriesExist(ctx, dirs...)
}

// ensureEmptyFileExists ensures that the containing directory exists, and the
// specified file exists. If it doesn't exist, it will write an empty file.
func ensureEmptyFileExists(ctx Context, file string) {
	ensureDirectoriesExist(ctx, filepath.Dir(file))
	if _, err := os.Stat(file); os.IsNotExist(err) {
		f, err := os.Create(file)
		if err != nil {
			ctx.Fatalf("Error creating %s: %q\n", file, err)
		}
		f.Close()
	} else if err != nil {
		ctx.Fatalf("Error checking %s: %q\n", file, err)
	}
}

// singleUnquote is similar to strconv.Unquote, but can handle multi-character strings inside single quotes.
func singleUnquote(str string) (string, bool) {
	if len(str) < 2 || str[0] != '\'' || str[len(str)-1] != '\'' {
		return "", false
	}
	return str[1 : len(str)-1], true
}

// decodeKeyValue decodes a key=value string
func decodeKeyValue(str string) (string, string, bool) {
	idx := strings.IndexRune(str, '=')
	if idx == -1 {
		return "", "", false
	}
	return str[:idx], str[idx+1:], true
}

// copyFile copies a file from src to dst. filepath.Dir(dst) must exist.
func copyFile(src, dst string) (int64, error) {
	source, err := os.Open(src)
	if err != nil {
		return 0, err
	}
	defer source.Close()

	destination, err := os.Create(dst)
	if err != nil {
		return 0, err
	}
	defer destination.Close()

	return io.Copy(destination, source)
}

// gzipFileToDir writes a compressed copy of src to destDir with the suffix ".gz".
func gzipFileToDir(src, destDir string) error {
	in, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("failed to open %s: %s", src, err.Error())
	}
	defer in.Close()

	dest := filepath.Join(destDir, filepath.Base(src)+".gz")

	out, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		return fmt.Errorf("failed to open %s: %s", dest, err.Error())
	}
	defer out.Close()
	gz := gzip.NewWriter(out)
	defer gz.Close()

	_, err = io.Copy(gz, in)
	if err != nil {
		return fmt.Errorf("failed to gzip %s: %s", dest, err.Error())
	}

	return nil
}
