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

import (
	"errors"

	"policy-manager/pkg/devicepolicy"
	"policy-manager/pkg/systemd"

	"policy-manager/protos"

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

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

const updateDisabledStrategy = "update_disabled"

func startOrStopUnit(systemdClient systemd.SystemdClient, unitName string, isStartUnit bool) error {
	if isStartUnit {
		glog.Infof("Starting service: %v", unitName)
		return systemdClient.StartUnit(unitName)
	} else {
		glog.Infof("Stopping service: %v", unitName)
		return systemdClient.StopUnit(unitName)
	}
}

// NewPolicyEnforcer returns a new PolicyEnforcer for applying the
// the COS device policy and status check
func NewPolicyEnforcer(systemdClient systemd.SystemdClient) *PolicyEnforcer {
	return &PolicyEnforcer{systemdClient}
}

// UpdateServiceState reads device policy from disk, and then apply
// the configuration to the instance. If the desired state is to be running,
// the function will start or stop the services to apply the configuration
// in device policy.
func (client *PolicyEnforcer) UpdateServiceState(cosDevicePolicyFile string, serviceMonitor map[string]string) error {
	// Reads the device policy files from disk to get desired state.
	config, err := devicepolicy.GetInstanceConfig(cosDevicePolicyFile)
	if err != nil {
		return err
	}

	// Gets the current status of services.
	serviceStatus, err := client.GetServiceStatus(serviceMonitor)

	if err != nil {
		return err
	}

	updateStateErr := false

	// Start or stop the services to reach desired state.
	if serviceStatus.GetMetrics() != config.GetMetricsEnabled() {
		if err := startOrStopUnit(client.systemdClient,
			serviceMonitor["metricsService"], config.GetMetricsEnabled()); err != nil {
			glog.Error(err)
			updateStateErr = true
		}
	}

	if serviceStatus.GetUpdateEngine() != config.GetUpdateStrategy() {
		updateStrategyMode := true
		if config.GetUpdateStrategy() == updateDisabledStrategy {
			updateStrategyMode = false
		}

		if err := startOrStopUnit(client.systemdClient,
			serviceMonitor["updateService"], updateStrategyMode); err != nil {
			glog.Error(err)
			updateStateErr = true
		}
	}

	if serviceStatus.GetLogging() != config.HealthMonitorConfig.GetLoggingEnabled() {
		if err := startOrStopUnit(client.systemdClient,
			serviceMonitor["loggingService"], config.HealthMonitorConfig.GetLoggingEnabled()); err != nil {
			glog.Error(err)
			updateStateErr = true
		}
	}

	if serviceStatus.GetMonitoring() != config.HealthMonitorConfig.GetMonitoringEnabled() {
		if err := startOrStopUnit(client.systemdClient,
			serviceMonitor["monitoringService"], config.HealthMonitorConfig.GetMonitoringEnabled()); err != nil {
			glog.Error(err)
			updateStateErr = true
		}
	}

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

// GetServiceStatus checks whether the services are running and returns their
// status in a InstanceStatus 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 *PolicyEnforcer) GetServiceStatus(serviceMonitor map[string]string) (*protos.InstanceStatus, error) {
	instanceStatus := new(protos.InstanceStatus)

	statusErr := false
	isRunning, err := client.systemdClient.IsUnitActiveRunning(serviceMonitor["metricsService"])
	if err != nil {
		glog.Error(err)
		statusErr = true
	} else {
		instanceStatus.Metrics = proto.Bool(isRunning)
	}

	isRunning, err = client.systemdClient.IsUnitActiveRunning(serviceMonitor["updateService"])
	if err != nil {
		glog.Error(err)
		statusErr = true

	} else {
		if isRunning {
			instanceStatus.UpdateEngine = proto.String("")
		} else {
			instanceStatus.UpdateEngine = proto.String(updateDisabledStrategy)
		}
	}

	isRunning, err = client.systemdClient.IsUnitActiveRunning(serviceMonitor["loggingService"])
	if err != nil {
		glog.Error(err)
		statusErr = true
	} else {
		instanceStatus.Logging = proto.Bool(isRunning)
	}

	isRunning, err = client.systemdClient.IsUnitActiveRunning(serviceMonitor["monitoringService"])
	if err != nil {
		glog.Error(err)
		statusErr = true

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

	if statusErr {
		return instanceStatus, errors.New("unable to get service status")
	}
	return instanceStatus, nil
}
