//----------------------------------------------------------------------------------------------------------------------
/// \file
/// <summary>Public C++ ScreenCapture API.</summary>
// Copyright (c) Microsoft Corporation.  All Rights Reserved.
//----------------------------------------------------------------------------------------------------------------------
#pragma once
#if defined(_WIN32)
#include "Wex.Common.h"

#include <Windows.h>

namespace WEX { namespace Common
{
#pragma warning(push)
#pragma warning(disable:26812) // It would be good to switch to enum class, but that would be a breaking change.
    /// <summary>
    /// The possible ImageFormats that a ScreenCapture can be saved in.
    /// </summary>
    namespace ImageFormats
    {
        enum Format
        {
            /// Uses a lossless format.
            Lossless = 0,

            /// Uses the HDPhoto format.
            HDPhoto,

            /// Uses the PNG format.
            PNG,

            /// Uses the BMP format.
            BMP,

            /// Uses the JPEG format.
            JPEG,

            /// Will use the lowest image format possible on this system (usually JPEG).
            LowQuality,

            /// \internal
            Unknown
        };
    }

    /// <summary>
    /// The possible settings for capturing the mouse cursor
    /// </summary>
    namespace ScreenCaptureOptions
    {
        enum Options
        {
            /// No options specified
            None = 0,

            /// Show the mouse cursor in the screen shot
            ShowMouseCursor = 1,

            /// \internal
            Unknown = 2
        };

        inline Options& operator|=(Options& lhs, Options rhs) noexcept
        {
            lhs = static_cast<ScreenCaptureOptions::Options>((static_cast<int>(lhs) | static_cast<int>(rhs)));
            return lhs;
        }

        inline Options operator|(Options lhs, Options rhs) noexcept
        {
            return lhs |= rhs;
        }

        inline int operator&(Options lhs, Options rhs) noexcept
        {
            return (static_cast<int>(lhs) & static_cast<int>(rhs));
        }
    }/* namespace ScreenCaptureOptions */

    class NoThrowString;

    /// <summary>
    /// Defines a class that provides the ability to save ScreenCaptures.
    /// </summary>
    class WEXCOMMON_API ScreenCapture final
    {
    public:
        /// <summary>Takes a screen capture of all monitors and saves it to disk without the mouse cursor included, and defaults to ImageFormats::LowQuality.</summary>
        /// <param name="pszFilePath">The file to save to.</param>
        static HRESULT __stdcall Save(const wchar_t* pszFilePath);

        /// <summary>Takes a screen capture of all monitors and saves it to disk in the specified ImageFormats::Format; does not capture the mouse cursor in the screenshot.</summary>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        static HRESULT __stdcall Save(const wchar_t* pszFilePath, ImageFormats::Format imageFormat);

        /// <summary>Takes a screen capture of all monitors and saves it to disk as ImageFormats::LowQuality; captures the mouse cursor in the screenshot if requested.</summary>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(const wchar_t* pszFilePath, ScreenCaptureOptions::Options captureOptions);

        /// <summary>Takes a screen capture of all monitors and saves it to disk in the spedified ImageFormats::Format; captures the mouse cursor in the screenshot if requested.</summary>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(const wchar_t* pszFilePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);


        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk without the mouse cursor included, and defaults to ImageFormats::LowQuality.</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="pszFilePath">The file to save to.</param>
        static HRESULT __stdcall Save(RECT rect, const wchar_t* pszFilePath);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the specified ImageFormats::Format; does not capture the mouse cursor in the screenshot.</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        static HRESULT __stdcall Save(RECT rect, const wchar_t* pszFilePath, ImageFormats::Format imageFormat);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk as ImageFormats::LowQuality; captures the mouse cursor in the screenshot if requested.</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(RECT rect, const wchar_t* pszFilePath, ScreenCaptureOptions::Options captureOptions);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the spedified ImageFormats::Format; captures the mouse cursor in the screenshot if requested.</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(RECT rect, const wchar_t* pszFilePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);


        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk without the mouse cursor included, and defaults to ImageFormats::LowQuality.</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="pszFilePath">The file to save to.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const wchar_t* pszFilePath);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the specified ImageFormats::Format; does not capture the mouse cursor in the screenshot.</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const wchar_t* pszFilePath,
                                      ImageFormats::Format imageFormat);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk as ImageFormats::LowQuality; captures the mouse cursor in the screenshot if requested.</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const wchar_t* pszFilePath, ScreenCaptureOptions::Options captureOptions);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the spedified ImageFormats::Format; captures the mouse cursor in the screenshot if requested.</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="pszFilePath">The file to save to.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const wchar_t* pszFilePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);


        /// <summary>Takes a screen capture of all monitors and saves it to disk without the mouse cursor included, and defaults to ImageFormats::LowQuality; also updates filePath if the file extension has been modified</summary>
        /// <param name="filePath"></param>
        static HRESULT __stdcall Save(NoThrowString& filePath);

        /// <summary>Takes a screen capture of all monitors and saves it to disk in the specified ImageFormats::Format; does not capture the mouse cursor in the screenshot; also updates filePath if the file extension has been modified</summary>
        /// <param name="filePath"></param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        static HRESULT __stdcall Save(NoThrowString& filePath, ImageFormats::Format imageFormat);

        /// <summary>Takes a screen capture of all monitors and saves it to disk as ImageFormats::LowQuality; captures the mouse cursor in the screenshot if requested; also updates filePath if the file extension has been modified</summary>
        /// <param name="filePath"></param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(NoThrowString& filePath, ScreenCaptureOptions::Options captureOptions);

        /// <summary>Takes a screen capture of all monitors and saves it to disk in the spedified ImageFormats::Format; captures the mouse cursor in the screenshot if requested; also updates filePath if the file extension has been modified</summary>
        /// <param name="filePath"></param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(NoThrowString& filePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);


        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk without the mouse cursor included, and defaults to ImageFormats::LowQuality; also updates filePath if the file extension has been modified</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="filePath"></param>
        static HRESULT __stdcall Save(RECT rect, NoThrowString& filePath);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the specified ImageFormats::Format; does not capture the mouse cursor in the screenshot; also updates filePath if the file extension has been modified</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="filePath"></param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        static HRESULT __stdcall Save(RECT rect, NoThrowString& filePath, ImageFormats::Format imageFormat);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk as ImageFormats::LowQuality; captures the mouse cursor in the screenshot if requested; also updates filePath if the file extension has been modified</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="filePath"></param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(RECT rect, NoThrowString& filePath, ScreenCaptureOptions::Options captureOptions);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the spedified ImageFormats::Format; captures the mouse cursor in the screenshot if requested; also updates filePath if the file extension has been modified</summary>
        /// <param name="rect">A RECT that defines the region of the Desktop to save - in Desktop co-ordinates.</param>
        /// <param name="filePath"></param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        /// <param name="imageFormat">The ImageFormats::Format to save as. Defaults to ImageFormats::LowQuality.</param>
        static HRESULT __stdcall Save(RECT rect, NoThrowString& filePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);


        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk without the mouse cursor included, and defaults to ImageFormats::LowQuality; also updates filePath if the file extension has been modified</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="filePath"></param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, NoThrowString& filePath);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the specified ImageFormats::Format; does not capture the mouse cursor in the screenshot; also updates filePath if the file extension has been modified</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="filePath"></param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, NoThrowString& filePath, ImageFormats::Format imageFormat);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk as ImageFormats::LowQuality; captures the mouse cursor in the screenshot if requested; also updates filePath if the file extension has been modified</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="filePath"></param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, NoThrowString& filePath, ScreenCaptureOptions::Options captureOptions);

        /// <summary>Takes a screen capture of a specific rectangle and saves it to disk in the spedified ImageFormats::Format; captures the mouse cursor in the screenshot if requested; also updates filePath if the file extension has been modified</summary>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="filePath"></param>
        /// <param name="imageFormat">The ImageFormats::Format to save as.</param>
        /// <param name="captureOptions">Whether or not to capture the mouse cursor in the screenshot.</param>
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, NoThrowString& filePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);

        // unsigned short exports
        #if defined(WEXCOMMON_FULL_BUILD)
        static HRESULT __stdcall Save(const unsigned short* pszFilePath);
        static HRESULT __stdcall Save(const unsigned short* pszFilePath, ImageFormats::Format imageFormat);
        static HRESULT __stdcall Save(const unsigned short* pszFilePath, ScreenCaptureOptions::Options captureOptions);
        static HRESULT __stdcall Save(const unsigned short* pszFilePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);

        static HRESULT __stdcall Save(RECT rect, const unsigned short* pszFilePath);
        static HRESULT __stdcall Save(RECT rect, const unsigned short* pszFilePath, ImageFormats::Format imageFormat);
        static HRESULT __stdcall Save(RECT rect, const unsigned short* pszFilePath, ScreenCaptureOptions::Options captureOptions);
        static HRESULT __stdcall Save(RECT rect, const unsigned short* pszFilePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);

        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const unsigned short* pszFilePath);
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const unsigned short* pszFilePath, ImageFormats::Format imageFormat);
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const unsigned short* pszFilePath, ScreenCaptureOptions::Options captureOptions);
        static HRESULT __stdcall Save(int left, int top, int right, int bottom, const unsigned short* pszFilePath, ImageFormats::Format imageFormat, ScreenCaptureOptions::Options captureOptions);
        #endif

    private:
        // Disallow construction of static class
        ScreenCapture() = delete;
        ~ScreenCapture() = delete;
        ScreenCapture(const ScreenCapture&) = delete;
        ScreenCapture& operator=(const ScreenCapture&) = delete;
    };
#pragma warning(pop)
}/* namespace Common */}/* namespace WEX */
#endif // #if defined(_WIN32)
