//----------------------------------------------------------------------------------------------------------------------
/// \file
/// <summary>API and data types for interacting with TAEF during Reboot and Disconnect scenarios.</summary>
// Copyright (c) Microsoft Corporation.  All Rights Reserved.
//----------------------------------------------------------------------------------------------------------------------
#pragma once
#if defined(_WIN32)
#include "TE.Common.h"

#pragma warning(push)
// Disable "Prefer enum class over enum".
#pragma warning(disable:26812)
namespace WEX { namespace TestExecution
{
    namespace RebootOption
    {
        enum Option
        {
            Rerun = 0x0,
            Continue = 0x1,
            // When running under DES or a TestMD, the test infrastructure waits for the OS shell to fully initialize
            // before launching TE.exe to have it run the remaining tests. The AvoidWaitingForShellInitialization option
            // can be used to have TAEF tell that test infrastructure to avoid this wait. This can be useful for tests that
            // need to run during OOBE. This currently only applies when running within a DES test pass or within a TestMD.
            AvoidWaitingForShellInitialization = 0x2,
        };
        inline Option operator|(Option option1, Option option2) noexcept
        {
            return static_cast<Option>(static_cast<unsigned int>(option1) | static_cast<unsigned int>(option2));
        }
        inline Option& operator|=(Option& option1, Option option2) noexcept
        {
            return (option1 = option1 | option2);
        }
    }/* namespace RebootOption */

#if !defined(__cplusplus_cli)
    enum class DisconnectOption
    {
        Default = 0,
        // By default, TAEF will fail any calls to Interruption::Reboot/RebootCustom if the test case had previously called
        // Interuption::Disconnect. However, if this option is used, that is switched so TAEF requires the test to call
        // Interruption::Reboot/RebootCustom later in the test case. If the test does not call Interruption::Reboot/RebootCustom
        // later, TAEF will fail the test. Note that it is never allowed to call a reboot API first then later call Disconnect
        // in the same test case.
        //
        // Another difference is that by default, tests may do only one disconnect after calling Interuption::Disconnect.
        // However, with this option, tests may disconnect from the network any number of times. Internally, this is because
        // TAEF shuts down the service that TestMD uses to communicate with the machine. (This implemenation detail is subject
        // to change.) This makes it so TestMD cannot connect even while the network on the device under test is still working.
        // The later reboot takes care of turning the service back on so TestMD can reconnect. From TestMD's perspective, it
        // will appear to just be a reboot that took a long time.
        TestCaseWillRebootLater = 0x1,
    };
    inline DisconnectOption operator|(DisconnectOption option1, DisconnectOption option2) noexcept
    {
        return static_cast<DisconnectOption>(static_cast<unsigned int>(option1) | static_cast<unsigned int>(option2));
    }
    inline DisconnectOption& operator|=(DisconnectOption& option1, DisconnectOption option2) noexcept
    {
        return (option1 = option1 | option2);
    }
#endif

    namespace Interruption
    {
        namespace Private
        {
#if !defined(__cplusplus_cli)
            extern "C" TECOMMON_API void TAEF_STDCALL Interruption_Disconnect(DisconnectOption) noexcept;
#endif

            extern "C" TECOMMON_API void TAEF_STDCALL Interruption_Reboot(RebootOption::Option option) noexcept;
            extern "C" TECOMMON_API void TAEF_STDCALL Interruption_RebootCustom(RebootOption::Option option) noexcept;
        }/* namespace Private */

#if !defined(__cplusplus_cli)
        inline void Disconnect(DisconnectOption option = DisconnectOption::Default) noexcept { Private::Interruption_Disconnect(option); }
#endif

        inline void Reboot(RebootOption::Option option) noexcept { return Private::Interruption_Reboot(option); }
        inline void RebootCustom(RebootOption::Option option) noexcept { return Private::Interruption_RebootCustom(option); }
    }/* namespace Interruption */
}/* namespace TestExecution */}/* namespace WEX */
#pragma warning(pop)
#endif // #if defined(_WIN32)
