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

//go:build stackdriver_alpha
// +build stackdriver_alpha

package policyenforcer

import (
	"errors"

	"policy_manager/devicepolicy"
	"policy_manager/systemd"

	"policy_manager/policymanagerproto"

	"github.com/golang/glog"
	"github.com/golang/protobuf/proto"
)

// policyEnforcerImpl implements the PolicyEnforcer interface.
type policyEnforcerImpl struct {
	// systemdClient is the interface used to call systemd API.
	systemdClient systemd.SystemdClient

	// manager is used to read content from device policy file.
	manager devicepolicy.Manager

	// health monitor is the interface to the logging and monitoring services.
	healthMonitor *HealthMonitor
}

// NewPolicyEnforcer returns a new PolicyEnforcer for applying the
// the COS device policy and status check
func NewPolicyEnforcer(systemdClient systemd.SystemdClient, manager devicepolicy.Manager, monitor *HealthMonitor) PolicyEnforcer {
	return &policyEnforcerImpl{systemdClient, manager, monitor}
}

func startOrStopUnit(systemdClient systemd.SystemdClient, unitName string, isStartUnit bool) error {
	if isStartUnit {
		return systemdClient.StartUnit(unitName)
	} else {
		return systemdClient.StopUnit(unitName)
	}
}

// UpdateHealthMonitorState reads device policy from disk, and then apply
// health monitor related configuration to the instance:
// If health monitor feature enforcement is on, the function will start or stop
// the health monitor services to apply the configuration in device policy.
func (client *policyEnforcerImpl) UpdateHealthMonitorState() error {
	// Reads the device policy files from disk to get desired state.
	config, err := client.manager.GetInstanceConfig()
	if err != nil {
		return err
	}
	// Returns when the health monitor feature enforcement is off.
	if config == nil || config.HealthMonitorConfig == nil || !config.HealthMonitorConfig.GetEnforced() {
		return nil
	}

	// Gets the current status of health monitor logging & logging.
	healthMonitorStatus, err := client.GetHealthMonitorStatus()
	if err != nil {
		return err
	}

	updateStateErr := false

	// Start or stop the health monitor services to reach desired state.
	if healthMonitorStatus.GetLogging() != config.HealthMonitorConfig.GetLoggingEnabled() {
		if err = startOrStopUnit(client.systemdClient,
			client.healthMonitor.LoggingService(), config.HealthMonitorConfig.GetLoggingEnabled()); err != nil {
			glog.Error(err)
			updateStateErr = true
		}
	}

	if healthMonitorStatus.GetMonitoring() != config.HealthMonitorConfig.GetMonitoringEnabled() {
		if err = startOrStopUnit(client.systemdClient,
			client.healthMonitor.MonitoringService(), config.HealthMonitorConfig.GetMonitoringEnabled()); err != nil {
			glog.Error(err)
			updateStateErr = true
		}
	}

	if updateStateErr {
		return errors.New("Unable to apply health monitor policy.")
	}
	return nil
}

// GetHealthMonitorStatus checks whether health monitor logging/monitoring service
// is running, and returns their status in a HealthMonitorStatus proto.
// Failure to check one service will result in a missing field in the returned
// proto, and will not affect checking the other service's status.
func (client *policyEnforcerImpl) GetHealthMonitorStatus() (*policymanagerproto.HealthMonitorStatus, error) {
	healthMonitorStatus := new(policymanagerproto.HealthMonitorStatus)

	statusErr := false

	isRunning, err := client.systemdClient.IsUnitActiveRunning(client.healthMonitor.LoggingService())
	if err != nil {
		glog.Error(err)
		statusErr = true
	} else {
		healthMonitorStatus.Logging = proto.Bool(isRunning)
	}

	isRunning, err = client.systemdClient.IsUnitActiveRunning(client.healthMonitor.MonitoringService())
	if err != nil {
		glog.Error(err)
		statusErr = true

	} else {
		healthMonitorStatus.Monitoring = proto.Bool(isRunning)
	}

	if statusErr {
		return healthMonitorStatus, errors.New("Unable to get health monitor status.")
	}
	return healthMonitorStatus, nil
}
