// Copyright 2021 Google LLC
//
// 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 logging

import (
	"io/ioutil"
	"os"
	"strings"
	"sync"

	"cloud.google.com/go/compute/metadata"
	mrpb "google.golang.org/genproto/googleapis/api/monitoredres"
)

// CommonResource sets the monitored resource associated with all log entries
// written from a Logger. If not provided, the resource is automatically
// detected based on the running environment (on GCE, GCR, GCF and GAE Standard only).
// This value can be overridden per-entry by setting an Entry's Resource field.
func CommonResource(r *mrpb.MonitoredResource) LoggerOption { return commonResource{r} }

type commonResource struct{ *mrpb.MonitoredResource }

func (r commonResource) set(l *Logger) { l.commonResource = r.MonitoredResource }

var detectedResource struct {
	pb   *mrpb.MonitoredResource
	once sync.Once
}

// isAppEngine returns true for both standard and flex
func isAppEngine() bool {
	_, service := os.LookupEnv("GAE_SERVICE")
	_, version := os.LookupEnv("GAE_VERSION")
	_, instance := os.LookupEnv("GAE_INSTANCE")

	return service && version && instance
}

func detectAppEngineResource() *mrpb.MonitoredResource {
	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil
	}
	if projectID == "" {
		projectID = os.Getenv("GOOGLE_CLOUD_PROJECT")
	}
	zone, err := metadata.Zone()
	if err != nil {
		return nil
	}

	return &mrpb.MonitoredResource{
		Type: "gae_app",
		Labels: map[string]string{
			"project_id":  projectID,
			"module_id":   os.Getenv("GAE_SERVICE"),
			"version_id":  os.Getenv("GAE_VERSION"),
			"instance_id": os.Getenv("GAE_INSTANCE"),
			"runtime":     os.Getenv("GAE_RUNTIME"),
			"zone":        zone,
		},
	}
}

func isCloudFunction() bool {
	// Reserved envvars in older function runtimes, e.g. Node.js 8, Python 3.7 and Go 1.11.
	_, name := os.LookupEnv("FUNCTION_NAME")
	_, region := os.LookupEnv("FUNCTION_REGION")
	_, entry := os.LookupEnv("ENTRY_POINT")

	// Reserved envvars in newer function runtimes.
	_, target := os.LookupEnv("FUNCTION_TARGET")
	_, signature := os.LookupEnv("FUNCTION_SIGNATURE_TYPE")
	_, service := os.LookupEnv("K_SERVICE")
	return (name && region && entry) || (target && signature && service)
}

func detectCloudFunction() *mrpb.MonitoredResource {
	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil
	}
	zone, err := metadata.Zone()
	if err != nil {
		return nil
	}
	// Newer functions runtimes store name in K_SERVICE.
	functionName, exists := os.LookupEnv("K_SERVICE")
	if !exists {
		functionName, _ = os.LookupEnv("FUNCTION_NAME")
	}
	return &mrpb.MonitoredResource{
		Type: "cloud_function",
		Labels: map[string]string{
			"project_id":    projectID,
			"region":        regionFromZone(zone),
			"function_name": functionName,
		},
	}
}

func isCloudRun() bool {
	_, config := os.LookupEnv("K_CONFIGURATION")
	_, service := os.LookupEnv("K_SERVICE")
	_, revision := os.LookupEnv("K_REVISION")
	return config && service && revision
}

func detectCloudRunResource() *mrpb.MonitoredResource {
	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil
	}
	zone, err := metadata.Zone()
	if err != nil {
		return nil
	}
	return &mrpb.MonitoredResource{
		Type: "cloud_run_revision",
		Labels: map[string]string{
			"project_id":         projectID,
			"location":           regionFromZone(zone),
			"service_name":       os.Getenv("K_SERVICE"),
			"revision_name":      os.Getenv("K_REVISION"),
			"configuration_name": os.Getenv("K_CONFIGURATION"),
		},
	}
}

func isKubernetesEngine() bool {
	clusterName, err := metadata.InstanceAttributeValue("cluster-name")
	// Note: InstanceAttributeValue can return "", nil
	if err != nil || clusterName == "" {
		return false
	}
	return true
}

func detectKubernetesResource() *mrpb.MonitoredResource {
	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil
	}
	zone, err := metadata.Zone()
	if err != nil {
		return nil
	}
	clusterName, err := metadata.InstanceAttributeValue("cluster-name")
	if err != nil {
		return nil
	}
	namespaceBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
	namespaceName := ""
	if err == nil {
		namespaceName = string(namespaceBytes)
	}
	return &mrpb.MonitoredResource{
		Type: "k8s_container",
		Labels: map[string]string{
			"cluster_name":   clusterName,
			"location":       zone,
			"project_id":     projectID,
			"pod_name":       os.Getenv("HOSTNAME"),
			"namespace_name": namespaceName,
			// To get the `container_name` label, users need to explicitly provide it.
			"container_name": os.Getenv("CONTAINER_NAME"),
		},
	}
}

func detectGCEResource() *mrpb.MonitoredResource {
	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil
	}
	id, err := metadata.InstanceID()
	if err != nil {
		return nil
	}
	zone, err := metadata.Zone()
	if err != nil {
		return nil
	}
	return &mrpb.MonitoredResource{
		Type: "gce_instance",
		Labels: map[string]string{
			"project_id":  projectID,
			"instance_id": id,
			"zone":        zone,
		},
	}
}

func detectResource() *mrpb.MonitoredResource {
	detectedResource.once.Do(func() {
		switch {
		// AppEngine, Functions, CloudRun, Kubernetes are detected first,
		// as metadata.OnGCE() erroneously returns true on these runtimes.
		case isAppEngine():
			detectedResource.pb = detectAppEngineResource()
		case isCloudFunction():
			detectedResource.pb = detectCloudFunction()
		case isCloudRun():
			detectedResource.pb = detectCloudRunResource()
		case isKubernetesEngine():
			detectedResource.pb = detectKubernetesResource()
		case metadata.OnGCE():
			detectedResource.pb = detectGCEResource()
		}
	})
	return detectedResource.pb
}

var resourceInfo = map[string]struct{ rtype, label string }{
	"organizations":   {"organization", "organization_id"},
	"folders":         {"folder", "folder_id"},
	"projects":        {"project", "project_id"},
	"billingAccounts": {"billing_account", "account_id"},
}

func monitoredResource(parent string) *mrpb.MonitoredResource {
	parts := strings.SplitN(parent, "/", 2)
	if len(parts) != 2 {
		return globalResource(parent)
	}
	info, ok := resourceInfo[parts[0]]
	if !ok {
		return globalResource(parts[1])
	}
	return &mrpb.MonitoredResource{
		Type:   info.rtype,
		Labels: map[string]string{info.label: parts[1]},
	}
}

func regionFromZone(zone string) string {
	cutoff := strings.LastIndex(zone, "-")
	if cutoff > 0 {
		return zone[:cutoff]
	}
	return zone
}

func globalResource(projectID string) *mrpb.MonitoredResource {
	return &mrpb.MonitoredResource{
		Type: "global",
		Labels: map[string]string{
			"project_id": projectID,
		},
	}
}
