
/*
 * This file is auto-generated from AndroidDrawerLayoutNativeComponent spec file in flow / TypeScript.
 */
// clang-format off
#pragma once

#include <NativeModules.h>

#ifdef RNW_NEW_ARCH
#include <JSValueComposition.h>

#include <winrt/Microsoft.ReactNative.Composition.h>
#include <winrt/Microsoft.UI.Composition.h>
#endif // #ifdef RNW_NEW_ARCH

#ifdef RNW_NEW_ARCH

namespace Microsoft::ReactNativeSpecs {

REACT_STRUCT(AndroidDrawerLayoutProps)
struct AndroidDrawerLayoutProps : winrt::implements<AndroidDrawerLayoutProps, winrt::Microsoft::ReactNative::IComponentProps> {
  AndroidDrawerLayoutProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom)
    : ViewProps(props)
  {
     if (cloneFrom) {
       auto cloneFromProps = cloneFrom.as<AndroidDrawerLayoutProps>();
       keyboardDismissMode = cloneFromProps->keyboardDismissMode;
       drawerBackgroundColor = cloneFromProps->drawerBackgroundColor;
       drawerPosition = cloneFromProps->drawerPosition;
       drawerWidth = cloneFromProps->drawerWidth;
       drawerLockMode = cloneFromProps->drawerLockMode;
       statusBarBackgroundColor = cloneFromProps->statusBarBackgroundColor;
       onDrawerSlide = cloneFromProps->onDrawerSlide;
       onDrawerStateChanged = cloneFromProps->onDrawerStateChanged;
       onDrawerOpen = cloneFromProps->onDrawerOpen;
       onDrawerClose = cloneFromProps->onDrawerClose;  
     }
  }

  void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
    winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
  }

  REACT_FIELD(keyboardDismissMode)
  std::optional<std::string> keyboardDismissMode;

  REACT_FIELD(drawerBackgroundColor)
  winrt::Microsoft::ReactNative::Color drawerBackgroundColor{nullptr};

  REACT_FIELD(drawerPosition)
  std::optional<std::string> drawerPosition;

  REACT_FIELD(drawerWidth)
  std::optional<float> drawerWidth{};

  REACT_FIELD(drawerLockMode)
  std::optional<std::string> drawerLockMode;

  REACT_FIELD(statusBarBackgroundColor)
  winrt::Microsoft::ReactNative::Color statusBarBackgroundColor{nullptr};

   // These fields can be used to determine if JS has registered for this event
  REACT_FIELD(onDrawerSlide)
  bool onDrawerSlide{false};

  REACT_FIELD(onDrawerStateChanged)
  bool onDrawerStateChanged{false};

  REACT_FIELD(onDrawerOpen)
  bool onDrawerOpen{false};

  REACT_FIELD(onDrawerClose)
  bool onDrawerClose{false};

  const winrt::Microsoft::ReactNative::ViewProps ViewProps;
};

REACT_STRUCT(AndroidDrawerLayoutSpec_onDrawerClose)
struct AndroidDrawerLayoutSpec_onDrawerClose {
};

REACT_STRUCT(AndroidDrawerLayoutSpec_onDrawerOpen)
struct AndroidDrawerLayoutSpec_onDrawerOpen {
};

REACT_STRUCT(AndroidDrawerLayoutSpec_onDrawerStateChanged)
struct AndroidDrawerLayoutSpec_onDrawerStateChanged {
  REACT_FIELD(drawerState)
  int32_t drawerState{};
};

REACT_STRUCT(AndroidDrawerLayoutSpec_onDrawerSlide)
struct AndroidDrawerLayoutSpec_onDrawerSlide {
  REACT_FIELD(offset)
  float offset{};
};

struct AndroidDrawerLayoutEventEmitter {
  AndroidDrawerLayoutEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter)
      : m_eventEmitter(eventEmitter) {}

  using OnDrawerSlide = AndroidDrawerLayoutSpec_onDrawerSlide;
  using OnDrawerStateChanged = AndroidDrawerLayoutSpec_onDrawerStateChanged;
  using OnDrawerOpen = AndroidDrawerLayoutSpec_onDrawerOpen;
  using OnDrawerClose = AndroidDrawerLayoutSpec_onDrawerClose;

  void onDrawerSlide(OnDrawerSlide &&value) const {
    m_eventEmitter.DispatchEvent(L"drawerSlide", [value = std::move(value)](const winrt::Microsoft::ReactNative::IJSValueWriter writer) {
      winrt::Microsoft::ReactNative::WriteValue(writer, value);
    });
  }

  void onDrawerStateChanged(OnDrawerStateChanged &&value) const {
    m_eventEmitter.DispatchEvent(L"drawerStateChanged", [value = std::move(value)](const winrt::Microsoft::ReactNative::IJSValueWriter writer) {
      winrt::Microsoft::ReactNative::WriteValue(writer, value);
    });
  }

  void onDrawerOpen(OnDrawerOpen &&value) const {
    m_eventEmitter.DispatchEvent(L"drawerOpen", [value = std::move(value)](const winrt::Microsoft::ReactNative::IJSValueWriter writer) {
      winrt::Microsoft::ReactNative::WriteValue(writer, value);
    });
  }

  void onDrawerClose(OnDrawerClose &&value) const {
    m_eventEmitter.DispatchEvent(L"drawerClose", [value = std::move(value)](const winrt::Microsoft::ReactNative::IJSValueWriter writer) {
      winrt::Microsoft::ReactNative::WriteValue(writer, value);
    });
  }

 private:
  winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr};
};

template<typename TUserData>
struct BaseAndroidDrawerLayout {

  virtual void UpdateProps(
    const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
    const winrt::com_ptr<AndroidDrawerLayoutProps> &newProps,
    const winrt::com_ptr<AndroidDrawerLayoutProps> &/*oldProps*/) noexcept {
    m_props = newProps;
  }

  // UpdateLayoutMetrics will only be called if this method is overridden
  virtual void UpdateLayoutMetrics(
    const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
    const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/,
    const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept {
  }

  // UpdateState will only be called if this method is overridden
  virtual void UpdateState(
    const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
    const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept {
  }

  virtual void UpdateEventEmitter(const std::shared_ptr<AndroidDrawerLayoutEventEmitter> &eventEmitter) noexcept {
    m_eventEmitter = eventEmitter;
  }

  // MountChildComponentView will only be called if this method is overridden
  virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
           const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept {
  }

  // UnmountChildComponentView will only be called if this method is overridden
  virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
           const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept {
  }

  // Initialize will only be called if this method is overridden
  virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept {
  }

  // CreateVisual will only be called if this method is overridden
  virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
    return view.as<winrt::Microsoft::ReactNative::Composition::ComponentView>().Compositor().CreateSpriteVisual();
  }

  // FinalizeUpdate will only be called if this method is overridden
  virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
                                        winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept {
  }

  // CreateAutomationPeer will only be called if this method is overridden
  virtual winrt::Windows::Foundation::IInspectable CreateAutomationPeer(const winrt::Microsoft::ReactNative::ComponentView & /*view*/,
                                        const winrt::Microsoft::ReactNative::CreateAutomationPeerArgs& /*args*/) noexcept {
    return nullptr;
  }

  // You must provide an implementation of this method to handle the "openDrawer" command
  virtual void HandleOpenDrawerCommand() noexcept = 0;

  // You must provide an implementation of this method to handle the "closeDrawer" command
  virtual void HandleCloseDrawerCommand() noexcept = 0;

  void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept {
    auto userData = view.UserData().as<TUserData>();
    auto commandName = args.CommandName();
    if (commandName == L"openDrawer") {

      userData->HandleOpenDrawerCommand();
      return;
    }

    if (commandName == L"closeDrawer") {

      userData->HandleCloseDrawerCommand();
      return;
    }
  }

  const std::shared_ptr<AndroidDrawerLayoutEventEmitter>& EventEmitter() const { return m_eventEmitter; }
  const winrt::com_ptr<AndroidDrawerLayoutProps>& Props() const { return m_props; }

private:
  winrt::com_ptr<AndroidDrawerLayoutProps> m_props;
  std::shared_ptr<AndroidDrawerLayoutEventEmitter> m_eventEmitter;
};

template <typename TUserData>
void RegisterAndroidDrawerLayoutNativeComponent(
    winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder,
    std::function<void(const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder&)> builderCallback) noexcept {
  packageBuilder.as<winrt::Microsoft::ReactNative::IReactPackageBuilderFabric>().AddViewComponent(
      L"AndroidDrawerLayout", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
        auto compBuilder = builder.as<winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder>();

        builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
                              const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept {
            return winrt::make<AndroidDrawerLayoutProps>(props, cloneFrom); 
        });

        builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                     const winrt::Microsoft::ReactNative::IComponentProps &newProps,
                                     const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept {
            auto userData = view.UserData().as<TUserData>();
            userData->UpdateProps(view, newProps ? newProps.as<AndroidDrawerLayoutProps>() : nullptr, oldProps ? oldProps.as<AndroidDrawerLayoutProps>() : nullptr);
        });

        compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                      const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics,
                                      const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept {
            auto userData = view.UserData().as<TUserData>();
            userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics);
        });

        builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                     const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept {
          auto userData = view.UserData().as<TUserData>();
          userData->UpdateEventEmitter(std::make_shared<AndroidDrawerLayoutEventEmitter>(eventEmitter));
        });

        if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::FinalizeUpdate != &BaseAndroidDrawerLayout<TUserData>::FinalizeUpdate) {
            builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                     winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept {
            auto userData = view.UserData().as<TUserData>();
            userData->FinalizeUpdate(view, mask);
          });
        } 

        if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::UpdateState != &BaseAndroidDrawerLayout<TUserData>::UpdateState) {
          builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                     const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
            auto userData = view.UserData().as<TUserData>();
            userData->UpdateState(view, newState);
          });
        }

        builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                          const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept {
          auto userData = view.UserData().as<TUserData>();
          userData->HandleCommand(view, args);
        });

        if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::MountChildComponentView != &BaseAndroidDrawerLayout<TUserData>::MountChildComponentView) {
          builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                      const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept {
            auto userData = view.UserData().as<TUserData>();
            return userData->MountChildComponentView(view, args);
          });
        }

        if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::UnmountChildComponentView != &BaseAndroidDrawerLayout<TUserData>::UnmountChildComponentView) {
          builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                      const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept {
            auto userData = view.UserData().as<TUserData>();
            return userData->UnmountChildComponentView(view, args);
          });
        }

        if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::CreateAutomationPeer != &BaseAndroidDrawerLayout<TUserData>::CreateAutomationPeer) {
            builder.SetCreateAutomationPeerHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
                                     const winrt::Microsoft::ReactNative::CreateAutomationPeerArgs& args) noexcept {
            auto userData = view.UserData().as<TUserData>();
            return userData->CreateAutomationPeer(view, args);
          });
        } 

        compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
          auto userData = winrt::make_self<TUserData>();
          if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::Initialize != &BaseAndroidDrawerLayout<TUserData>::Initialize) {
            userData->Initialize(view);
          }
          view.UserData(*userData);
        });

        if CONSTEXPR_SUPPORTED_ON_VIRTUAL_FN_ADDRESS (&TUserData::CreateVisual != &BaseAndroidDrawerLayout<TUserData>::CreateVisual) {
          compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
            auto userData = view.UserData().as<TUserData>();
            return userData->CreateVisual(view);
          });
        }

        // Allow app to further customize the builder
        if (builderCallback) {
          builderCallback(compBuilder);
        }
      });
}

} // namespace Microsoft::ReactNativeSpecs

#endif // #ifdef RNW_NEW_ARCH
