// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build windows
// +build windows

package mgr

import (
	"errors"
	"syscall"
	"time"
	"unsafe"

	"golang.org/x/sys/internal/unsafeheader"
	"golang.org/x/sys/windows"
)

const (
	// Possible recovery actions that the service control manager can perform.
	NoAction       = windows.SC_ACTION_NONE        // no action
	ComputerReboot = windows.SC_ACTION_REBOOT      // reboot the computer
	ServiceRestart = windows.SC_ACTION_RESTART     // restart the service
	RunCommand     = windows.SC_ACTION_RUN_COMMAND // run a command
)

// RecoveryAction represents an action that the service control manager can perform when service fails.
// A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller.
type RecoveryAction struct {
	Type  int           // one of NoAction, ComputerReboot, ServiceRestart or RunCommand
	Delay time.Duration // the time to wait before performing the specified action
}

// SetRecoveryActions sets actions that service controller performs when service fails and
// the time after which to reset the service failure count to zero if there are no failures, in seconds.
// Specify INFINITE to indicate that service failure count should never be reset.
func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error {
	if recoveryActions == nil {
		return errors.New("recoveryActions cannot be nil")
	}
	actions := []windows.SC_ACTION{}
	for _, a := range recoveryActions {
		action := windows.SC_ACTION{
			Type:  uint32(a.Type),
			Delay: uint32(a.Delay.Nanoseconds() / 1000000),
		}
		actions = append(actions, action)
	}
	rActions := windows.SERVICE_FAILURE_ACTIONS{
		ActionsCount: uint32(len(actions)),
		Actions:      &actions[0],
		ResetPeriod:  resetPeriod,
	}
	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}

// RecoveryActions returns actions that service controller performs when service fails.
// The service control manager counts the number of times service s has failed since the system booted.
// The count is reset to 0 if the service has not failed for ResetPeriod seconds.
// When the service fails for the Nth time, the service controller performs the action specified in element [N-1] of returned slice.
// If N is greater than slice length, the service controller repeats the last action in the slice.
func (s *Service) RecoveryActions() ([]RecoveryAction, error) {
	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
	if err != nil {
		return nil, err
	}
	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
	if p.Actions == nil {
		return nil, err
	}

	var actions []windows.SC_ACTION
	hdr := (*unsafeheader.Slice)(unsafe.Pointer(&actions))
	hdr.Data = unsafe.Pointer(p.Actions)
	hdr.Len = int(p.ActionsCount)
	hdr.Cap = int(p.ActionsCount)

	var recoveryActions []RecoveryAction
	for _, action := range actions {
		recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
	}
	return recoveryActions, nil
}

// ResetRecoveryActions deletes both reset period and array of failure actions.
func (s *Service) ResetRecoveryActions() error {
	actions := make([]windows.SC_ACTION, 1)
	rActions := windows.SERVICE_FAILURE_ACTIONS{
		Actions: &actions[0],
	}
	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}

// ResetPeriod is the time after which to reset the service failure
// count to zero if there are no failures, in seconds.
func (s *Service) ResetPeriod() (uint32, error) {
	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
	if err != nil {
		return 0, err
	}
	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
	return p.ResetPeriod, nil
}

// SetRebootMessage sets service s reboot message.
// If msg is "", the reboot message is deleted and no message is broadcast.
func (s *Service) SetRebootMessage(msg string) error {
	rActions := windows.SERVICE_FAILURE_ACTIONS{
		RebootMsg: syscall.StringToUTF16Ptr(msg),
	}
	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}

// RebootMessage is broadcast to server users before rebooting in response to the ComputerReboot service controller action.
func (s *Service) RebootMessage() (string, error) {
	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
	if err != nil {
		return "", err
	}
	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
	return windows.UTF16PtrToString(p.RebootMsg), nil
}

// SetRecoveryCommand sets the command line of the process to execute in response to the RunCommand service controller action.
// If cmd is "", the command is deleted and no program is run when the service fails.
func (s *Service) SetRecoveryCommand(cmd string) error {
	rActions := windows.SERVICE_FAILURE_ACTIONS{
		Command: syscall.StringToUTF16Ptr(cmd),
	}
	return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
}

// RecoveryCommand is the command line of the process to execute in response to the RunCommand service controller action. This process runs under the same account as the service.
func (s *Service) RecoveryCommand() (string, error) {
	b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
	if err != nil {
		return "", err
	}
	p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
	return windows.UTF16PtrToString(p.Command), nil
}
