// Copyright 2015 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.

// Implements the environment JSON file handling for serializing the
// environment variables that were used in soong_build so that soong_ui can
// check whether they have changed
package shared

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"sort"
)

type envFileEntry struct{ Key, Value string }
type envFileData []envFileEntry

// Serializes the given environment variable name/value map into JSON formatted bytes by converting
// to envFileEntry values and marshaling them.
//
// e.g. OUT_DIR = "out"
// is converted to:
// {
//     "Key": "OUT_DIR",
//     "Value": "out",
// },
func EnvFileContents(envDeps map[string]string) ([]byte, error) {
	contents := make(envFileData, 0, len(envDeps))
	for key, value := range envDeps {
		contents = append(contents, envFileEntry{key, value})
	}

	sort.Sort(contents)

	data, err := json.MarshalIndent(contents, "", "    ")
	if err != nil {
		return nil, err
	}

	data = append(data, '\n')

	return data, nil
}

// Reads and deserializes a Soong environment file located at the given file path to determine its
// staleness. If any environment variable values have changed, it prints them out and returns true.
// Failing to read or parse the file also causes it to return true.
func StaleEnvFile(filepath string, getenv func(string) string) (bool, error) {
	data, err := ioutil.ReadFile(filepath)
	if err != nil {
		return true, err
	}

	var contents envFileData

	err = json.Unmarshal(data, &contents)
	if err != nil {
		return true, err
	}

	var changed []string
	for _, entry := range contents {
		key := entry.Key
		old := entry.Value
		cur := getenv(key)
		if old != cur {
			changed = append(changed, fmt.Sprintf("%s (%q -> %q)", key, old, cur))
		}
	}

	if len(changed) > 0 {
		fmt.Printf("environment variables changed value:\n")
		for _, s := range changed {
			fmt.Printf("   %s\n", s)
		}
		return true, nil
	}

	return false, nil
}

// Deserializes and environment serialized by EnvFileContents() and returns it
// as a map[string]string.
func EnvFromFile(envFile string) (map[string]string, error) {
	result := make(map[string]string)
	data, err := ioutil.ReadFile(envFile)
	if err != nil {
		return result, err
	}

	var contents envFileData
	err = json.Unmarshal(data, &contents)
	if err != nil {
		return result, err
	}

	for _, entry := range contents {
		result[entry.Key] = entry.Value
	}

	return result, nil
}

// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
func (e envFileData) Len() int {
	return len(e)
}

func (e envFileData) Less(i, j int) bool {
	return e[i].Key < e[j].Key
}

func (e envFileData) Swap(i, j int) {
	e[i], e[j] = e[j], e[i]
}

var _ sort.Interface = envFileData{}
