/*
 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors

 * 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 config

import (
	"context"
	"errors"
	"os"
	"strings"

	"github.com/opencord/voltha-lib-go/v7/pkg/log"
)

const (
	defaultTracingStatusKey        = "trace_publish"   // kvstore key containing tracing configuration status
	defaultLogCorrelationStatusKey = "log_correlation" // kvstore key containing log correlation configuration status
)

// ComponentLogFeatureController represents Configuration for Logging related features of Tracing and Log
// Correlation of specific Voltha component.
type ComponentLogFeaturesController struct {
	ComponentName               string
	componentNameConfig         *ComponentConfig
	configManager               *ConfigManager
	initialTracingStatus        bool // Initial default tracing status set by helm chart
	initialLogCorrelationStatus bool // Initial default log correlation status set by helm chart
}

func NewComponentLogFeaturesController(ctx context.Context, cm *ConfigManager) (*ComponentLogFeaturesController, error) {
	logger.Debug(ctx, "creating-new-component-log-features-controller")
	componentName := os.Getenv("COMPONENT_NAME")
	if componentName == "" {
		return nil, errors.New("Unable to retrieve PoD Component Name from Runtime env")
	}

	tracingStatus := log.GetGlobalLFM().GetTracePublishingStatus()
	logCorrelationStatus := log.GetGlobalLFM().GetLogCorrelationStatus()

	return &ComponentLogFeaturesController{
		ComponentName:               componentName,
		componentNameConfig:         nil,
		configManager:               cm,
		initialTracingStatus:        tracingStatus,
		initialLogCorrelationStatus: logCorrelationStatus,
	}, nil

}

// StartLogFeaturesConfigProcessing persists initial config of Log Features into Config Store before
// starting the loading and processing of Configuration updates
func StartLogFeaturesConfigProcessing(cm *ConfigManager, ctx context.Context) {
	cc, err := NewComponentLogFeaturesController(ctx, cm)
	if err != nil {
		logger.Errorw(ctx, "unable-to-construct-component-log-features-controller-instance-for-monitoring", log.Fields{"error": err})
		return
	}

	cc.componentNameConfig = cm.InitComponentConfig(cc.ComponentName, ConfigTypeLogFeatures)
	logger.Debugw(ctx, "component-log-features-config", log.Fields{"cc-component-name-config": cc.componentNameConfig})

	cc.persistInitialLogFeaturesConfigs(ctx)

	cc.processLogFeaturesConfig(ctx)
}

// Method to persist Initial status of Log Correlation and Tracing features (as set from command line)
// into config store (etcd kvstore), if not set yet
func (cc *ComponentLogFeaturesController) persistInitialLogFeaturesConfigs(ctx context.Context) {

	_, err := cc.componentNameConfig.Retrieve(ctx, defaultTracingStatusKey)
	if err != nil {
		statusString := "DISABLED"
		if cc.initialTracingStatus {
			statusString = "ENABLED"
		}
		err = cc.componentNameConfig.Save(ctx, defaultTracingStatusKey, statusString)
		if err != nil {
			logger.Errorw(ctx, "failed-to-persist-component-initial-tracing-status-at-startup", log.Fields{"error": err, "tracingstatus": statusString})
		}
	}

	_, err = cc.componentNameConfig.Retrieve(ctx, defaultLogCorrelationStatusKey)
	if err != nil {
		statusString := "DISABLED"
		if cc.initialLogCorrelationStatus {
			statusString = "ENABLED"
		}
		err = cc.componentNameConfig.Save(ctx, defaultLogCorrelationStatusKey, statusString)
		if err != nil {
			logger.Errorw(ctx, "failed-to-persist-component-initial-log-correlation-status-at-startup", log.Fields{"error": err, "logcorrelationstatus": statusString})
		}
	}
}

// processLogFeaturesConfig will first load and apply configuration of log features. Then it will start waiting for any changes
// made to configuration in config store (etcd) and apply the same
func (cc *ComponentLogFeaturesController) processLogFeaturesConfig(ctx context.Context) {

	// Load and apply Tracing Status and log correlation status for first time
	cc.loadAndApplyTracingStatusUpdate(ctx)
	cc.loadAndApplyLogCorrelationStatusUpdate(ctx)

	componentConfigEventChan := cc.componentNameConfig.MonitorForConfigChange(ctx)

	// process the change events received on the channel
	var configEvent *ConfigChangeEvent
	for {
		select {
		case <-ctx.Done():
			return

		case configEvent = <-componentConfigEventChan:
			logger.Debugw(ctx, "processing-log-features-config-change", log.Fields{"ChangeType": configEvent.ChangeType, "Package": configEvent.ConfigAttribute})

			if strings.HasSuffix(configEvent.ConfigAttribute, defaultTracingStatusKey) {
				cc.loadAndApplyTracingStatusUpdate(ctx)
			} else if strings.HasSuffix(configEvent.ConfigAttribute, defaultLogCorrelationStatusKey) {
				cc.loadAndApplyLogCorrelationStatusUpdate(ctx)
			}
		}
	}

}

func (cc *ComponentLogFeaturesController) loadAndApplyTracingStatusUpdate(ctx context.Context) {

	desiredTracingStatus, err := cc.componentNameConfig.Retrieve(ctx, defaultTracingStatusKey)
	if err != nil || desiredTracingStatus == "" {
		logger.Warn(ctx, "unable-to-retrieve-tracing-status-from-config-store")
		return
	}

	if desiredTracingStatus != "ENABLED" && desiredTracingStatus != "DISABLED" {
		logger.Warnw(ctx, "unsupported-tracing-status-configured-in-config-store", log.Fields{"failed-tracing-status": desiredTracingStatus, "tracing-status": log.GetGlobalLFM().GetTracePublishingStatus()})
		return
	}

	logger.Debugw(ctx, "retrieved-tracing-status", log.Fields{"tracing-status": desiredTracingStatus})

	log.GetGlobalLFM().SetTracePublishingStatus(desiredTracingStatus == "ENABLED")
}

func (cc *ComponentLogFeaturesController) loadAndApplyLogCorrelationStatusUpdate(ctx context.Context) {

	desiredLogCorrelationStatus, err := cc.componentNameConfig.Retrieve(ctx, defaultLogCorrelationStatusKey)
	if err != nil || desiredLogCorrelationStatus == "" {
		logger.Warn(ctx, "unable-to-retrieve-log-correlation-status-from-config-store")
		return
	}

	if desiredLogCorrelationStatus != "ENABLED" && desiredLogCorrelationStatus != "DISABLED" {
		logger.Warnw(ctx, "unsupported-log-correlation-status-configured-in-config-store", log.Fields{"failed-log-correlation-status": desiredLogCorrelationStatus, "log-correlation-status": log.GetGlobalLFM().GetLogCorrelationStatus()})
		return
	}

	logger.Debugw(ctx, "retrieved-log-correlation-status", log.Fields{"log-correlation-status": desiredLogCorrelationStatus})

	log.GetGlobalLFM().SetLogCorrelationStatus(desiredLogCorrelationStatus == "ENABLED")
}
