// 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 configfetcher

import (
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"policy-manager/protos"

	metadataServer "cloud.google.com/go/compute/metadata"
	"github.com/golang/glog"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
)

const (
	// gciLegacyConfigKey is the GCE metadata Key used to specify user's preference of
	// the InstanceConfig. The value of this key should be JSON representation
	// of the InstanceConfig proto.
	// DEPRECATED. Use the specific keys below.
	gciLegacyConfigKey = "gci-instance-config"

	// Metadata keys for each InstanceConfig attribute that users can specify.
	// Although we continue supporting metadata key with 'gci-' prefix, users
	// should use the keys with 'cos-' prefix if possible.
	gciKeyUpdateStrategy = "gci-update-strategy"
	gciKeyMetricsEnabled = "gci-metrics-enabled"

	// Metadata keys with 'cos-' prefix
	cosKeyUpdateStrategy = "cos-update-strategy"
	cosKeyMetricsEnabled = "cos-metrics-enabled"

	// Metadata keys for GCP-related features.
	keyGoogleLoggingEnabled    = "google-logging-enabled"
	keyGoogleMonitoringEnabled = "google-monitoring-enabled"

	// The sleep time when watching user config failed.
	retryInterval = 5 * time.Second
)

// PollUserConfig watches the update of the InstanceConfig specified by user in GCE
// metadata. It repeatedly sends request to wait for update of userConfig. When an update
// is returned, PollUserConfig compares it to the cached userConfig and outputs to the
// channel if it is really updated.
func PollUserConfig(out chan *protos.InstanceConfig, gceMetadataURL string) {
	var userConfig, lastUserConfig *protos.InstanceConfig
	var err error
	etag := ""
	lastUserConfig = nil
	for {
		userConfig, etag, err = getUserConfig(etag, gceMetadataURL)
		if err != nil {
			time.Sleep(retryInterval)
			etag = ""
			continue // Retry forever.
		}
		// Check whether userConfig is updated.
		if proto.Equal(lastUserConfig, userConfig) {
			glog.V(1).Infof(
				"Instance custom metadata are updated but instanceConfig stays the same: {%+v}",
				userConfig)
			continue
		}
		// To cache the original userConfig, a deep copy is necessary.
		lastUserConfig = proto.Clone(userConfig).(*protos.InstanceConfig)
		out <- userConfig
	}
}

// getUserConfig gets the content of the instance custom metadata keys'.
// Then getUserConfig parses the metadata keys and returns userConfig.
func getUserConfig(lastEtag string, gceMetadataURL string) (*protos.InstanceConfig, string, error) {
	rawMetadata, etag, err := FetchMetadata(lastEtag, gceMetadataURL)
	if err != nil {
		glog.Errorf("Failed to fetch metadata from metadata server: %s", err)
		return nil, "", err
	}

	metadata, err := parseRawMetadata(rawMetadata)
	if err != nil {
		glog.Errorf("Failed to parse raw metadata: %s", err)
		return nil, "", err
	}
	glog.Infof("Current value of instance custom metadata keys: %v", metadata)
	userConfig, err := getUserConfigFromMetadata(metadata)
	if err != nil {
		glog.Errorf("Failed to resolve userconfig: %s", err)
		return nil, "", err
	}
	return userConfig, etag, nil
}

// Converts instance custom metadata from string to key:value pairs.
func parseRawMetadata(rawMetadata string) (map[string]string, error) {
	output := make(map[string]string)

	if err := json.Unmarshal([]byte(rawMetadata), &output); err != nil {
		return nil, err
	}
	return output, nil
}

// GetInstanceID returns the id of the instance.
func GetInstanceID() (uint64, error) {
	var resp, err = metadataServer.InstanceID()
	if err != nil {
		return 0, err
	}

	return strconv.ParseUint(string(resp), 10, 64)
}

// Helper function to get metadata value of a key with 'cos-' prefix and the
// corresponding key with 'gci-' prefix. For example, 'cos-update-strategy' and
// 'gci-update-strategy'. The value of 'gci-' key is returned only if the function
// fail to get the value of 'cos-' key.
func getCOSGCIConfigSetting(cosKey string, gciKey string, metadata map[string]string) (string, bool) {
	value, ok := metadata[cosKey]
	if !ok {
		value, ok = metadata[gciKey]
	}
	return value, ok
}

// Gets user config based on the metadata keys. An empty InstanceConfig is returned
// if there is no InstanceConfig-related metadata in the pairs.
func getUserConfigFromMetadata(metadata map[string]string) (*protos.InstanceConfig, error) {
	var configStr string
	var err error
	var ok, boolean bool
	userConfig := new(protos.InstanceConfig)
	userConfig.HealthMonitorConfig = new(protos.HealthMonitorConfig)

	// Get legacy instance config from metadata. This is deprecated, but if this is still
	// being specified, use it and ignore others.
	if configStr, ok = getCOSGCIConfigSetting("", gciLegacyConfigKey, metadata); ok {
		if configStr != "" {
			if err := jsonpb.UnmarshalString(configStr, userConfig); err != nil {
				return nil, fmt.Errorf("failed to unmarshal InstanceConfig %s: %s", configStr, err)
			}
		}
		return userConfig, nil
	}

	// Get individual config settings. Keys with 'cos-' prefix have the priority.
	if configStr, ok = getCOSGCIConfigSetting(cosKeyUpdateStrategy, gciKeyUpdateStrategy, metadata); ok {
		if configStr == "update_disabled" {
			userConfig.UpdateStrategy = proto.String(configStr)
		} else {
			userConfig.UpdateStrategy = proto.String("")
		}
	}

	if configStr, ok = getCOSGCIConfigSetting(cosKeyMetricsEnabled, gciKeyMetricsEnabled, metadata); ok {
		if boolean, err = strconv.ParseBool(configStr); err == nil {
			userConfig.MetricsEnabled = proto.Bool(boolean)
		}
	}

	if configStr, ok := getCOSGCIConfigSetting(keyGoogleLoggingEnabled, "", metadata); ok {
		if boolean, err = strconv.ParseBool(configStr); err == nil {
			userConfig.HealthMonitorConfig.LoggingEnabled = proto.Bool(boolean)
		}
	}

	if configStr, ok := getCOSGCIConfigSetting(keyGoogleMonitoringEnabled, "", metadata); ok {
		if boolean, err = strconv.ParseBool(configStr); err == nil {
			userConfig.HealthMonitorConfig.MonitoringEnabled = proto.Bool(boolean)
		}
	}

	// Set Enforced to true if user is enabling logging or monitoring.
	if userConfig.HealthMonitorConfig.GetLoggingEnabled() || userConfig.HealthMonitorConfig.GetMonitoringEnabled() {
		userConfig.HealthMonitorConfig.Enforced = proto.Bool(true)
	}

	return userConfig, nil
}
