// Copyright (c) The NodeRT Contributors
// All rights reserved.
//
// 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
//
// THIS CODE IS PROVIDED ON AN  *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions
// and limitations under the License.

// TODO: Verify that this is is still needed..
#define NTDDI_VERSION 0x06010000

#include <v8.h>
#include "nan.h"
#include <string>
#include <ppltasks.h>
#include "CollectionsConverter.h"
#include "CollectionsWrap.h"
#include "node-async.h"
#include "NodeRtUtils.h"
#include "OpaqueWrapper.h"
#include "WrapperBase.h"

#using <Windows.WinMD>

// this undefs fixes the issues of compiling Windows.Data.Json, Windows.Storag.FileProperties, and Windows.Stroage.Search
// Some of the node header files brings windows definitions with the same names as some of the WinRT methods
#undef DocumentProperties
#undef GetObject
#undef CreateEvent
#undef FindText
#undef SendMessage

const char* REGISTRATION_TOKEN_MAP_PROPERTY_NAME = "__registrationTokenMap__";

using v8::Array;
using v8::String;
using v8::Value;
using v8::Boolean;
using v8::Integer;
using v8::FunctionTemplate;
using v8::Object;
using v8::Local;
using v8::Function;
using v8::Date;
using v8::Number;
using v8::PropertyAttribute;
using v8::Primitive;
using Nan::HandleScope;
using Nan::Persistent;
using Nan::Undefined;
using Nan::True;
using Nan::False;
using Nan::Null;
using Nan::MaybeLocal;
using Nan::EscapableHandleScope;
using Nan::HandleScope;
using Nan::TryCatch;
using namespace concurrency;

namespace NodeRT { namespace Windows { namespace Gaming { namespace Input { 
  v8::Local<v8::Value> WrapArcadeStick(::Windows::Gaming::Input::ArcadeStick^ wintRtInstance);
  ::Windows::Gaming::Input::ArcadeStick^ UnwrapArcadeStick(Local<Value> value);
  
  v8::Local<v8::Value> WrapFlightStick(::Windows::Gaming::Input::FlightStick^ wintRtInstance);
  ::Windows::Gaming::Input::FlightStick^ UnwrapFlightStick(Local<Value> value);
  
  v8::Local<v8::Value> WrapGamepad(::Windows::Gaming::Input::Gamepad^ wintRtInstance);
  ::Windows::Gaming::Input::Gamepad^ UnwrapGamepad(Local<Value> value);
  
  v8::Local<v8::Value> WrapHeadset(::Windows::Gaming::Input::Headset^ wintRtInstance);
  ::Windows::Gaming::Input::Headset^ UnwrapHeadset(Local<Value> value);
  
  v8::Local<v8::Value> WrapIGameController(::Windows::Gaming::Input::IGameController^ wintRtInstance);
  ::Windows::Gaming::Input::IGameController^ UnwrapIGameController(Local<Value> value);
  
  v8::Local<v8::Value> WrapIGameControllerBatteryInfo(::Windows::Gaming::Input::IGameControllerBatteryInfo^ wintRtInstance);
  ::Windows::Gaming::Input::IGameControllerBatteryInfo^ UnwrapIGameControllerBatteryInfo(Local<Value> value);
  
  v8::Local<v8::Value> WrapRacingWheel(::Windows::Gaming::Input::RacingWheel^ wintRtInstance);
  ::Windows::Gaming::Input::RacingWheel^ UnwrapRacingWheel(Local<Value> value);
  
  v8::Local<v8::Value> WrapRawGameController(::Windows::Gaming::Input::RawGameController^ wintRtInstance);
  ::Windows::Gaming::Input::RawGameController^ UnwrapRawGameController(Local<Value> value);
  
  v8::Local<v8::Value> WrapUINavigationController(::Windows::Gaming::Input::UINavigationController^ wintRtInstance);
  ::Windows::Gaming::Input::UINavigationController^ UnwrapUINavigationController(Local<Value> value);
  



  static void InitArcadeStickButtonsEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("ArcadeStickButtons").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::None)));
    Nan::Set(enumObject, Nan::New<String>("stickUp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::StickUp)));
    Nan::Set(enumObject, Nan::New<String>("stickDown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::StickDown)));
    Nan::Set(enumObject, Nan::New<String>("stickLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::StickLeft)));
    Nan::Set(enumObject, Nan::New<String>("stickRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::StickRight)));
    Nan::Set(enumObject, Nan::New<String>("action1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Action1)));
    Nan::Set(enumObject, Nan::New<String>("action2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Action2)));
    Nan::Set(enumObject, Nan::New<String>("action3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Action3)));
    Nan::Set(enumObject, Nan::New<String>("action4").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Action4)));
    Nan::Set(enumObject, Nan::New<String>("action5").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Action5)));
    Nan::Set(enumObject, Nan::New<String>("action6").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Action6)));
    Nan::Set(enumObject, Nan::New<String>("special1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Special1)));
    Nan::Set(enumObject, Nan::New<String>("special2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::ArcadeStickButtons::Special2)));
  }

  static void InitFlightStickButtonsEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("FlightStickButtons").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::FlightStickButtons::None)));
    Nan::Set(enumObject, Nan::New<String>("firePrimary").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::FlightStickButtons::FirePrimary)));
    Nan::Set(enumObject, Nan::New<String>("fireSecondary").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::FlightStickButtons::FireSecondary)));
  }

  static void InitGameControllerButtonLabelEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("GameControllerButtonLabel").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::None)));
    Nan::Set(enumObject, Nan::New<String>("xboxBack").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxBack)));
    Nan::Set(enumObject, Nan::New<String>("xboxStart").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxStart)));
    Nan::Set(enumObject, Nan::New<String>("xboxMenu").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxMenu)));
    Nan::Set(enumObject, Nan::New<String>("xboxView").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxView)));
    Nan::Set(enumObject, Nan::New<String>("xboxUp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxUp)));
    Nan::Set(enumObject, Nan::New<String>("xboxDown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxDown)));
    Nan::Set(enumObject, Nan::New<String>("xboxLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxLeft)));
    Nan::Set(enumObject, Nan::New<String>("xboxRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxRight)));
    Nan::Set(enumObject, Nan::New<String>("xboxA").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxA)));
    Nan::Set(enumObject, Nan::New<String>("xboxB").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxB)));
    Nan::Set(enumObject, Nan::New<String>("xboxX").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxX)));
    Nan::Set(enumObject, Nan::New<String>("xboxY").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxY)));
    Nan::Set(enumObject, Nan::New<String>("xboxLeftBumper").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxLeftBumper)));
    Nan::Set(enumObject, Nan::New<String>("xboxLeftTrigger").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxLeftTrigger)));
    Nan::Set(enumObject, Nan::New<String>("xboxLeftStickButton").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxLeftStickButton)));
    Nan::Set(enumObject, Nan::New<String>("xboxRightBumper").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxRightBumper)));
    Nan::Set(enumObject, Nan::New<String>("xboxRightTrigger").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxRightTrigger)));
    Nan::Set(enumObject, Nan::New<String>("xboxRightStickButton").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxRightStickButton)));
    Nan::Set(enumObject, Nan::New<String>("xboxPaddle1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxPaddle1)));
    Nan::Set(enumObject, Nan::New<String>("xboxPaddle2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxPaddle2)));
    Nan::Set(enumObject, Nan::New<String>("xboxPaddle3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxPaddle3)));
    Nan::Set(enumObject, Nan::New<String>("xboxPaddle4").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::XboxPaddle4)));
    Nan::Set(enumObject, Nan::New<String>("mode").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Mode)));
    Nan::Set(enumObject, Nan::New<String>("select").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Select)));
    Nan::Set(enumObject, Nan::New<String>("menu").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Menu)));
    Nan::Set(enumObject, Nan::New<String>("view").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::View)));
    Nan::Set(enumObject, Nan::New<String>("back").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Back)));
    Nan::Set(enumObject, Nan::New<String>("start").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Start)));
    Nan::Set(enumObject, Nan::New<String>("options").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Options)));
    Nan::Set(enumObject, Nan::New<String>("share").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Share)));
    Nan::Set(enumObject, Nan::New<String>("up").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Up)));
    Nan::Set(enumObject, Nan::New<String>("down").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Down)));
    Nan::Set(enumObject, Nan::New<String>("left").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Left)));
    Nan::Set(enumObject, Nan::New<String>("right").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Right)));
    Nan::Set(enumObject, Nan::New<String>("letterA").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterA)));
    Nan::Set(enumObject, Nan::New<String>("letterB").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterB)));
    Nan::Set(enumObject, Nan::New<String>("letterC").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterC)));
    Nan::Set(enumObject, Nan::New<String>("letterL").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterL)));
    Nan::Set(enumObject, Nan::New<String>("letterR").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterR)));
    Nan::Set(enumObject, Nan::New<String>("letterX").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterX)));
    Nan::Set(enumObject, Nan::New<String>("letterY").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterY)));
    Nan::Set(enumObject, Nan::New<String>("letterZ").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LetterZ)));
    Nan::Set(enumObject, Nan::New<String>("cross").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Cross)));
    Nan::Set(enumObject, Nan::New<String>("circle").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Circle)));
    Nan::Set(enumObject, Nan::New<String>("square").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Square)));
    Nan::Set(enumObject, Nan::New<String>("triangle").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Triangle)));
    Nan::Set(enumObject, Nan::New<String>("leftBumper").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LeftBumper)));
    Nan::Set(enumObject, Nan::New<String>("leftTrigger").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LeftTrigger)));
    Nan::Set(enumObject, Nan::New<String>("leftStickButton").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::LeftStickButton)));
    Nan::Set(enumObject, Nan::New<String>("left1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Left1)));
    Nan::Set(enumObject, Nan::New<String>("left2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Left2)));
    Nan::Set(enumObject, Nan::New<String>("left3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Left3)));
    Nan::Set(enumObject, Nan::New<String>("rightBumper").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::RightBumper)));
    Nan::Set(enumObject, Nan::New<String>("rightTrigger").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::RightTrigger)));
    Nan::Set(enumObject, Nan::New<String>("rightStickButton").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::RightStickButton)));
    Nan::Set(enumObject, Nan::New<String>("right1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Right1)));
    Nan::Set(enumObject, Nan::New<String>("right2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Right2)));
    Nan::Set(enumObject, Nan::New<String>("right3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Right3)));
    Nan::Set(enumObject, Nan::New<String>("paddle1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Paddle1)));
    Nan::Set(enumObject, Nan::New<String>("paddle2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Paddle2)));
    Nan::Set(enumObject, Nan::New<String>("paddle3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Paddle3)));
    Nan::Set(enumObject, Nan::New<String>("paddle4").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Paddle4)));
    Nan::Set(enumObject, Nan::New<String>("plus").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Plus)));
    Nan::Set(enumObject, Nan::New<String>("minus").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Minus)));
    Nan::Set(enumObject, Nan::New<String>("downLeftArrow").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::DownLeftArrow)));
    Nan::Set(enumObject, Nan::New<String>("dialLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::DialLeft)));
    Nan::Set(enumObject, Nan::New<String>("dialRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::DialRight)));
    Nan::Set(enumObject, Nan::New<String>("suspension").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerButtonLabel::Suspension)));
  }

  static void InitGameControllerSwitchKindEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("GameControllerSwitchKind").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("twoWay").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchKind::TwoWay)));
    Nan::Set(enumObject, Nan::New<String>("fourWay").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchKind::FourWay)));
    Nan::Set(enumObject, Nan::New<String>("eightWay").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchKind::EightWay)));
  }

  static void InitGameControllerSwitchPositionEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("GameControllerSwitchPosition").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("center").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::Center)));
    Nan::Set(enumObject, Nan::New<String>("up").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::Up)));
    Nan::Set(enumObject, Nan::New<String>("upRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::UpRight)));
    Nan::Set(enumObject, Nan::New<String>("right").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::Right)));
    Nan::Set(enumObject, Nan::New<String>("downRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::DownRight)));
    Nan::Set(enumObject, Nan::New<String>("down").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::Down)));
    Nan::Set(enumObject, Nan::New<String>("downLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::DownLeft)));
    Nan::Set(enumObject, Nan::New<String>("left").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::Left)));
    Nan::Set(enumObject, Nan::New<String>("upLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GameControllerSwitchPosition::UpLeft)));
  }

  static void InitGamepadButtonsEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("GamepadButtons").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::None)));
    Nan::Set(enumObject, Nan::New<String>("menu").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::Menu)));
    Nan::Set(enumObject, Nan::New<String>("view").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::View)));
    Nan::Set(enumObject, Nan::New<String>("a").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::A)));
    Nan::Set(enumObject, Nan::New<String>("b").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::B)));
    Nan::Set(enumObject, Nan::New<String>("x").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::X)));
    Nan::Set(enumObject, Nan::New<String>("y").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::Y)));
    Nan::Set(enumObject, Nan::New<String>("dPadUp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::DPadUp)));
    Nan::Set(enumObject, Nan::New<String>("dPadDown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::DPadDown)));
    Nan::Set(enumObject, Nan::New<String>("dPadLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::DPadLeft)));
    Nan::Set(enumObject, Nan::New<String>("dPadRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::DPadRight)));
    Nan::Set(enumObject, Nan::New<String>("leftShoulder").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::LeftShoulder)));
    Nan::Set(enumObject, Nan::New<String>("rightShoulder").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::RightShoulder)));
    Nan::Set(enumObject, Nan::New<String>("leftThumbstick").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::LeftThumbstick)));
    Nan::Set(enumObject, Nan::New<String>("rightThumbstick").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::RightThumbstick)));
    Nan::Set(enumObject, Nan::New<String>("paddle1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::Paddle1)));
    Nan::Set(enumObject, Nan::New<String>("paddle2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::Paddle2)));
    Nan::Set(enumObject, Nan::New<String>("paddle3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::Paddle3)));
    Nan::Set(enumObject, Nan::New<String>("paddle4").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::GamepadButtons::Paddle4)));
  }

  static void InitOptionalUINavigationButtonsEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("OptionalUINavigationButtons").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::None)));
    Nan::Set(enumObject, Nan::New<String>("context1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::Context1)));
    Nan::Set(enumObject, Nan::New<String>("context2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::Context2)));
    Nan::Set(enumObject, Nan::New<String>("context3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::Context3)));
    Nan::Set(enumObject, Nan::New<String>("context4").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::Context4)));
    Nan::Set(enumObject, Nan::New<String>("pageUp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::PageUp)));
    Nan::Set(enumObject, Nan::New<String>("pageDown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::PageDown)));
    Nan::Set(enumObject, Nan::New<String>("pageLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::PageLeft)));
    Nan::Set(enumObject, Nan::New<String>("pageRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::PageRight)));
    Nan::Set(enumObject, Nan::New<String>("scrollUp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::ScrollUp)));
    Nan::Set(enumObject, Nan::New<String>("scrollDown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::ScrollDown)));
    Nan::Set(enumObject, Nan::New<String>("scrollLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::ScrollLeft)));
    Nan::Set(enumObject, Nan::New<String>("scrollRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::OptionalUINavigationButtons::ScrollRight)));
  }

  static void InitRacingWheelButtonsEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("RacingWheelButtons").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::None)));
    Nan::Set(enumObject, Nan::New<String>("previousGear").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::PreviousGear)));
    Nan::Set(enumObject, Nan::New<String>("nextGear").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::NextGear)));
    Nan::Set(enumObject, Nan::New<String>("dPadUp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::DPadUp)));
    Nan::Set(enumObject, Nan::New<String>("dPadDown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::DPadDown)));
    Nan::Set(enumObject, Nan::New<String>("dPadLeft").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::DPadLeft)));
    Nan::Set(enumObject, Nan::New<String>("dPadRight").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::DPadRight)));
    Nan::Set(enumObject, Nan::New<String>("button1").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button1)));
    Nan::Set(enumObject, Nan::New<String>("button2").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button2)));
    Nan::Set(enumObject, Nan::New<String>("button3").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button3)));
    Nan::Set(enumObject, Nan::New<String>("button4").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button4)));
    Nan::Set(enumObject, Nan::New<String>("button5").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button5)));
    Nan::Set(enumObject, Nan::New<String>("button6").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button6)));
    Nan::Set(enumObject, Nan::New<String>("button7").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button7)));
    Nan::Set(enumObject, Nan::New<String>("button8").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button8)));
    Nan::Set(enumObject, Nan::New<String>("button9").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button9)));
    Nan::Set(enumObject, Nan::New<String>("button10").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button10)));
    Nan::Set(enumObject, Nan::New<String>("button11").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button11)));
    Nan::Set(enumObject, Nan::New<String>("button12").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button12)));
    Nan::Set(enumObject, Nan::New<String>("button13").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button13)));
    Nan::Set(enumObject, Nan::New<String>("button14").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button14)));
    Nan::Set(enumObject, Nan::New<String>("button15").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button15)));
    Nan::Set(enumObject, Nan::New<String>("button16").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RacingWheelButtons::Button16)));
  }

  static void InitRequiredUINavigationButtonsEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("RequiredUINavigationButtons").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::None)));
    Nan::Set(enumObject, Nan::New<String>("menu").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Menu)));
    Nan::Set(enumObject, Nan::New<String>("view").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::View)));
    Nan::Set(enumObject, Nan::New<String>("accept").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Accept)));
    Nan::Set(enumObject, Nan::New<String>("cancel").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Cancel)));
    Nan::Set(enumObject, Nan::New<String>("up").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Up)));
    Nan::Set(enumObject, Nan::New<String>("down").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Down)));
    Nan::Set(enumObject, Nan::New<String>("left").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Left)));
    Nan::Set(enumObject, Nan::New<String>("right").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Gaming::Input::RequiredUINavigationButtons::Right)));
  }

  static bool IsArcadeStickReadingJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    return true;
  }

  ::Windows::Gaming::Input::ArcadeStickReading ArcadeStickReadingFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::ArcadeStickReading returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Timestamp = static_cast<unsigned __int64>(Nan::To<int64_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Buttons = static_cast<::Windows::Gaming::Input::ArcadeStickButtons>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    return returnValue;
  }

  Local<Value> ArcadeStickReadingToJsObject(::Windows::Gaming::Input::ArcadeStickReading value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New<String>("timestamp").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Timestamp)));
    Nan::Set(obj, Nan::New<String>("buttons").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.Buttons)));

    return scope.Escape(obj);
  }
  static bool IsFlightStickReadingJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("hatSwitch").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("roll").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("pitch").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("yaw").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("throttle").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    return true;
  }

  ::Windows::Gaming::Input::FlightStickReading FlightStickReadingFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::FlightStickReading returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Timestamp = static_cast<unsigned __int64>(Nan::To<int64_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Buttons = static_cast<::Windows::Gaming::Input::FlightStickButtons>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("hatSwitch").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.HatSwitch = static_cast<::Windows::Gaming::Input::GameControllerSwitchPosition>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("roll").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Roll = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("pitch").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Pitch = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("yaw").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Yaw = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("throttle").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Throttle = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    return returnValue;
  }

  Local<Value> FlightStickReadingToJsObject(::Windows::Gaming::Input::FlightStickReading value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New<String>("timestamp").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Timestamp)));
    Nan::Set(obj, Nan::New<String>("buttons").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.Buttons)));
    Nan::Set(obj, Nan::New<String>("hatSwitch").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.HatSwitch)));
    Nan::Set(obj, Nan::New<String>("roll").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Roll)));
    Nan::Set(obj, Nan::New<String>("pitch").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Pitch)));
    Nan::Set(obj, Nan::New<String>("yaw").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Yaw)));
    Nan::Set(obj, Nan::New<String>("throttle").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Throttle)));

    return scope.Escape(obj);
  }
  static bool IsGamepadReadingJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("leftTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("rightTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("leftThumbstickX").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("leftThumbstickY").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("rightThumbstickX").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("rightThumbstickY").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    return true;
  }

  ::Windows::Gaming::Input::GamepadReading GamepadReadingFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::GamepadReading returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Timestamp = static_cast<unsigned __int64>(Nan::To<int64_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Buttons = static_cast<::Windows::Gaming::Input::GamepadButtons>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("leftTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.LeftTrigger = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("rightTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.RightTrigger = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("leftThumbstickX").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.LeftThumbstickX = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("leftThumbstickY").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.LeftThumbstickY = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("rightThumbstickX").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.RightThumbstickX = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("rightThumbstickY").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.RightThumbstickY = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    return returnValue;
  }

  Local<Value> GamepadReadingToJsObject(::Windows::Gaming::Input::GamepadReading value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New<String>("timestamp").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Timestamp)));
    Nan::Set(obj, Nan::New<String>("buttons").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.Buttons)));
    Nan::Set(obj, Nan::New<String>("leftTrigger").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.LeftTrigger)));
    Nan::Set(obj, Nan::New<String>("rightTrigger").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.RightTrigger)));
    Nan::Set(obj, Nan::New<String>("leftThumbstickX").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.LeftThumbstickX)));
    Nan::Set(obj, Nan::New<String>("leftThumbstickY").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.LeftThumbstickY)));
    Nan::Set(obj, Nan::New<String>("rightThumbstickX").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.RightThumbstickX)));
    Nan::Set(obj, Nan::New<String>("rightThumbstickY").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.RightThumbstickY)));

    return scope.Escape(obj);
  }
  static bool IsGamepadVibrationJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    symbol = Nan::New<String>("leftMotor").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("rightMotor").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("leftTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("rightTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    return true;
  }

  ::Windows::Gaming::Input::GamepadVibration GamepadVibrationFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::GamepadVibration returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    symbol = Nan::New<String>("leftMotor").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.LeftMotor = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("rightMotor").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.RightMotor = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("leftTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.LeftTrigger = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("rightTrigger").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.RightTrigger = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    return returnValue;
  }

  Local<Value> GamepadVibrationToJsObject(::Windows::Gaming::Input::GamepadVibration value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New<String>("leftMotor").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.LeftMotor)));
    Nan::Set(obj, Nan::New<String>("rightMotor").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.RightMotor)));
    Nan::Set(obj, Nan::New<String>("leftTrigger").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.LeftTrigger)));
    Nan::Set(obj, Nan::New<String>("rightTrigger").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.RightTrigger)));

    return scope.Escape(obj);
  }
  static bool IsGamingInputPreviewContractJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    return true;
  }

  ::Windows::Gaming::Input::GamingInputPreviewContract GamingInputPreviewContractFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::GamingInputPreviewContract returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    return returnValue;
  }

  Local<Value> GamingInputPreviewContractToJsObject(::Windows::Gaming::Input::GamingInputPreviewContract value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();


    return scope.Escape(obj);
  }
  static bool IsRacingWheelReadingJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("patternShifterGear").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("wheel").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("throttle").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("brake").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("clutch").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("handbrake").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    return true;
  }

  ::Windows::Gaming::Input::RacingWheelReading RacingWheelReadingFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::RacingWheelReading returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Timestamp = static_cast<unsigned __int64>(Nan::To<int64_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("buttons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Buttons = static_cast<::Windows::Gaming::Input::RacingWheelButtons>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("patternShifterGear").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.PatternShifterGear = static_cast<int>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("wheel").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Wheel = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("throttle").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Throttle = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("brake").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Brake = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("clutch").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Clutch = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    symbol = Nan::New<String>("handbrake").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Handbrake = Nan::To<double>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0.0);
    }
    
    return returnValue;
  }

  Local<Value> RacingWheelReadingToJsObject(::Windows::Gaming::Input::RacingWheelReading value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New<String>("timestamp").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Timestamp)));
    Nan::Set(obj, Nan::New<String>("buttons").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.Buttons)));
    Nan::Set(obj, Nan::New<String>("patternShifterGear").ToLocalChecked(), Nan::New<Integer>(value.PatternShifterGear));
    Nan::Set(obj, Nan::New<String>("wheel").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Wheel)));
    Nan::Set(obj, Nan::New<String>("throttle").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Throttle)));
    Nan::Set(obj, Nan::New<String>("brake").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Brake)));
    Nan::Set(obj, Nan::New<String>("clutch").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Clutch)));
    Nan::Set(obj, Nan::New<String>("handbrake").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Handbrake)));

    return scope.Escape(obj);
  }
  static bool IsUINavigationReadingJsObject(Local<Value> value) {
    if (!value->IsObject()) {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsNumber()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("requiredButtons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    symbol = Nan::New<String>("optionalButtons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      if (!Nan::Get(obj,symbol).ToLocalChecked()->IsInt32()) {
        return false;
      }
    }
    
    return true;
  }

  ::Windows::Gaming::Input::UINavigationReading UINavigationReadingFromJsObject(Local<Value> value) {
    HandleScope scope;
    ::Windows::Gaming::Input::UINavigationReading returnValue;

    if (!value->IsObject()) {
      Nan::ThrowError(Nan::TypeError(NodeRT::Utils::NewString(L"Unexpected type, expected an object")));
      return returnValue;
    }

    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();
    Local<String> symbol;

    symbol = Nan::New<String>("timestamp").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.Timestamp = static_cast<unsigned __int64>(Nan::To<int64_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("requiredButtons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.RequiredButtons = static_cast<::Windows::Gaming::Input::RequiredUINavigationButtons>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    symbol = Nan::New<String>("optionalButtons").ToLocalChecked();
    if (Nan::Has(obj, symbol).FromMaybe(false)) {
      returnValue.OptionalButtons = static_cast<::Windows::Gaming::Input::OptionalUINavigationButtons>(Nan::To<int32_t>(Nan::Get(obj,symbol).ToLocalChecked()).FromMaybe(0));
    }
    
    return returnValue;
  }

  Local<Value> UINavigationReadingToJsObject(::Windows::Gaming::Input::UINavigationReading value) {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    Nan::Set(obj, Nan::New<String>("timestamp").ToLocalChecked(), Nan::New<Number>(static_cast<double>(value.Timestamp)));
    Nan::Set(obj, Nan::New<String>("requiredButtons").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.RequiredButtons)));
    Nan::Set(obj, Nan::New<String>("optionalButtons").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(value.OptionalButtons)));

    return scope.Escape(obj);
  }


  class ArcadeStick : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("ArcadeStick").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getButtonLabel", GetButtonLabel);
            Nan::SetPrototypeMethod(localRef, "getCurrentReading", GetCurrentReading);
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          


          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "fromGameController", FromGameController);
        Nan::SetAccessor(constructor, Nan::New<String>("arcadeSticks").ToLocalChecked(), ArcadeSticksGetter);
        


        Nan::Set(exports, Nan::New<String>("ArcadeStick").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      ArcadeStick(::Windows::Gaming::Input::ArcadeStick^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::ArcadeStick^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::ArcadeStick^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      ArcadeStick *wrapperInstance = new ArcadeStick(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::ArcadeStick^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::ArcadeStick^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapArcadeStick(winRtInstance));
    }


    static void GetButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This())) {
        return;
      }

      ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::Gaming::Input::ArcadeStickButtons arg0 = static_cast<::Windows::Gaming::Input::ArcadeStickButtons>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetCurrentReading(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This())) {
        return;
      }

      ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Gaming::Input::ArcadeStickReading result;
          result = wrapper->_instance->GetCurrentReading();
          info.GetReturnValue().Set(ArcadeStickReadingToJsObject(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This())) {
        return;
      }

      ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void FromGameController(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0]))
      {
        try
        {
          ::Windows::Gaming::Input::IGameController^ arg0 = UnwrapIGameController(info[0]);
          
          ::Windows::Gaming::Input::ArcadeStick^ result;
          result = ::Windows::Gaming::Input::ArcadeStick::FromGameController(arg0);
          info.GetReturnValue().Set(WrapArcadeStick(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This())) {
        return;
      }

      ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This())) {
        return;
      }

      ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This())) {
        return;
      }

      ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void ArcadeSticksGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      try
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::ArcadeStick^>^ result = ::Windows::Gaming::Input::ArcadeStick::ArcadeSticks;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::ArcadeStick^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::ArcadeStick^ val) -> Local<Value> {
              return WrapArcadeStick(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::ArcadeStick^ {
              return UnwrapArcadeStick(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      

    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"arcadeStickAdded", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::ArcadeStick::ArcadeStickAdded::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::ArcadeStick^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::ArcadeStick^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapArcadeStick(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"arcadeStickRemoved", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::ArcadeStick::ArcadeStickRemoved::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::ArcadeStick^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::ArcadeStick^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapArcadeStick(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"arcadeStickAdded", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"arcadeStickRemoved", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ArcadeStick^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          ArcadeStick *wrapper = ArcadeStick::Unwrap<ArcadeStick>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"arcadeStickAdded", str))
        {
          ::Windows::Gaming::Input::ArcadeStick::ArcadeStickAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"arcadeStickRemoved", str))
        {
          ::Windows::Gaming::Input::ArcadeStick::ArcadeStickRemoved::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::ArcadeStick^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapArcadeStick(::Windows::Gaming::Input::ArcadeStick^ wintRtInstance);
      friend ::Windows::Gaming::Input::ArcadeStick^ UnwrapArcadeStick(Local<Value> value);
  };

  Persistent<FunctionTemplate> ArcadeStick::s_constructorTemplate;

  v8::Local<v8::Value> WrapArcadeStick(::Windows::Gaming::Input::ArcadeStick^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(ArcadeStick::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::ArcadeStick^ UnwrapArcadeStick(Local<Value> value) {
     return ArcadeStick::Unwrap<ArcadeStick>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitArcadeStick(Local<Object> exports) {
    ArcadeStick::Init(exports);
  }

  class FlightStick : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("FlightStick").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getButtonLabel", GetButtonLabel);
            Nan::SetPrototypeMethod(localRef, "getCurrentReading", GetCurrentReading);
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          


          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("hatSwitchKind").ToLocalChecked(), HatSwitchKindGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "fromGameController", FromGameController);
        Nan::SetAccessor(constructor, Nan::New<String>("flightSticks").ToLocalChecked(), FlightSticksGetter);
        


        Nan::Set(exports, Nan::New<String>("FlightStick").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      FlightStick(::Windows::Gaming::Input::FlightStick^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::FlightStick^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::FlightStick^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      FlightStick *wrapperInstance = new FlightStick(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::FlightStick^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::FlightStick^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapFlightStick(winRtInstance));
    }


    static void GetButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::Gaming::Input::FlightStickButtons arg0 = static_cast<::Windows::Gaming::Input::FlightStickButtons>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetCurrentReading(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Gaming::Input::FlightStickReading result;
          result = wrapper->_instance->GetCurrentReading();
          info.GetReturnValue().Set(FlightStickReadingToJsObject(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void FromGameController(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0]))
      {
        try
        {
          ::Windows::Gaming::Input::IGameController^ arg0 = UnwrapIGameController(info[0]);
          
          ::Windows::Gaming::Input::FlightStick^ result;
          result = ::Windows::Gaming::Input::FlightStick::FromGameController(arg0);
          info.GetReturnValue().Set(WrapFlightStick(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void HatSwitchKindGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      try  {
        ::Windows::Gaming::Input::GameControllerSwitchKind result = wrapper->_instance->HatSwitchKind;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This())) {
        return;
      }

      FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void FlightSticksGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      try
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::FlightStick^>^ result = ::Windows::Gaming::Input::FlightStick::FlightSticks;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::FlightStick^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::FlightStick^ val) -> Local<Value> {
              return WrapFlightStick(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::FlightStick^ {
              return UnwrapFlightStick(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      

    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"flightStickAdded", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::FlightStick::FlightStickAdded::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::FlightStick^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::FlightStick^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapFlightStick(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"flightStickRemoved", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::FlightStick::FlightStickRemoved::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::FlightStick^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::FlightStick^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapFlightStick(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"flightStickAdded", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"flightStickRemoved", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::FlightStick^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          FlightStick *wrapper = FlightStick::Unwrap<FlightStick>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"flightStickAdded", str))
        {
          ::Windows::Gaming::Input::FlightStick::FlightStickAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"flightStickRemoved", str))
        {
          ::Windows::Gaming::Input::FlightStick::FlightStickRemoved::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::FlightStick^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapFlightStick(::Windows::Gaming::Input::FlightStick^ wintRtInstance);
      friend ::Windows::Gaming::Input::FlightStick^ UnwrapFlightStick(Local<Value> value);
  };

  Persistent<FunctionTemplate> FlightStick::s_constructorTemplate;

  v8::Local<v8::Value> WrapFlightStick(::Windows::Gaming::Input::FlightStick^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(FlightStick::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::FlightStick^ UnwrapFlightStick(Local<Value> value) {
     return FlightStick::Unwrap<FlightStick>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitFlightStick(Local<Object> exports) {
    FlightStick::Init(exports);
  }

  class Gamepad : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("Gamepad").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getCurrentReading", GetCurrentReading);
            Nan::SetPrototypeMethod(localRef, "getButtonLabel", GetButtonLabel);
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          


          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("vibration").ToLocalChecked(), VibrationGetter, VibrationSetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "fromGameController", FromGameController);
        Nan::SetAccessor(constructor, Nan::New<String>("gamepads").ToLocalChecked(), GamepadsGetter);
        


        Nan::Set(exports, Nan::New<String>("Gamepad").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      Gamepad(::Windows::Gaming::Input::Gamepad^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::Gamepad^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::Gamepad^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      Gamepad *wrapperInstance = new Gamepad(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::Gamepad^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::Gamepad^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapGamepad(winRtInstance));
    }


    static void GetCurrentReading(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Gaming::Input::GamepadReading result;
          result = wrapper->_instance->GetCurrentReading();
          info.GetReturnValue().Set(GamepadReadingToJsObject(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::Gaming::Input::GamepadButtons arg0 = static_cast<::Windows::Gaming::Input::GamepadButtons>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void FromGameController(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0]))
      {
        try
        {
          ::Windows::Gaming::Input::IGameController^ arg0 = UnwrapIGameController(info[0]);
          
          ::Windows::Gaming::Input::Gamepad^ result;
          result = ::Windows::Gaming::Input::Gamepad::FromGameController(arg0);
          info.GetReturnValue().Set(WrapGamepad(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VibrationGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      try  {
        ::Windows::Gaming::Input::GamepadVibration result = wrapper->_instance->Vibration;
        info.GetReturnValue().Set(GamepadVibrationToJsObject(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VibrationSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info) {
      HandleScope scope;

      if (!IsGamepadVibrationJsObject(value)) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This())) {
        return;
      }

      Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());

      try {

        ::Windows::Gaming::Input::GamepadVibration winRtValue = GamepadVibrationFromJsObject(value);

        wrapper->_instance->Vibration = winRtValue;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
      


    static void GamepadsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      try
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::Gamepad^>^ result = ::Windows::Gaming::Input::Gamepad::Gamepads;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::Gamepad^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::Gamepad^ val) -> Local<Value> {
              return WrapGamepad(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::Gamepad^ {
              return UnwrapGamepad(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      

    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"gamepadAdded", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::Gamepad::GamepadAdded::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::Gamepad^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::Gamepad^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapGamepad(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"gamepadRemoved", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::Gamepad::GamepadRemoved::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::Gamepad^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::Gamepad^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapGamepad(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"gamepadAdded", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"gamepadRemoved", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Gamepad^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          Gamepad *wrapper = Gamepad::Unwrap<Gamepad>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"gamepadAdded", str))
        {
          ::Windows::Gaming::Input::Gamepad::GamepadAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"gamepadRemoved", str))
        {
          ::Windows::Gaming::Input::Gamepad::GamepadRemoved::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::Gamepad^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapGamepad(::Windows::Gaming::Input::Gamepad^ wintRtInstance);
      friend ::Windows::Gaming::Input::Gamepad^ UnwrapGamepad(Local<Value> value);
  };

  Persistent<FunctionTemplate> Gamepad::s_constructorTemplate;

  v8::Local<v8::Value> WrapGamepad(::Windows::Gaming::Input::Gamepad^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(Gamepad::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::Gamepad^ UnwrapGamepad(Local<Value> value) {
     return Gamepad::Unwrap<Gamepad>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitGamepad(Local<Object> exports) {
    Gamepad::Init(exports);
  }

  class Headset : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("Headset").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          



          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("captureDeviceId").ToLocalChecked(), CaptureDeviceIdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("renderDeviceId").ToLocalChecked(), RenderDeviceIdGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("Headset").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      Headset(::Windows::Gaming::Input::Headset^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::Headset^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Headset^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::Headset^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      Headset *wrapperInstance = new Headset(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Headset^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::Headset^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::Headset^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapHeadset(winRtInstance));
    }


    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Headset^>(info.This())) {
        return;
      }

      Headset *wrapper = Headset::Unwrap<Headset>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void CaptureDeviceIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Headset^>(info.This())) {
        return;
      }

      Headset *wrapper = Headset::Unwrap<Headset>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->CaptureDeviceId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void RenderDeviceIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::Headset^>(info.This())) {
        return;
      }

      Headset *wrapper = Headset::Unwrap<Headset>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->RenderDeviceId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Gaming::Input::Headset^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapHeadset(::Windows::Gaming::Input::Headset^ wintRtInstance);
      friend ::Windows::Gaming::Input::Headset^ UnwrapHeadset(Local<Value> value);
  };

  Persistent<FunctionTemplate> Headset::s_constructorTemplate;

  v8::Local<v8::Value> WrapHeadset(::Windows::Gaming::Input::Headset^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(Headset::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::Headset^ UnwrapHeadset(Local<Value> value) {
     return Headset::Unwrap<Headset>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitHeadset(Local<Object> exports) {
    Headset::Init(exports);
  }

  class IGameController : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("IGameController").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);




          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("IGameController").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      IGameController(::Windows::Gaming::Input::IGameController^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::IGameController^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::IGameController^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      IGameController *wrapperInstance = new IGameController(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::IGameController^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::IGameController^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapIGameController(winRtInstance));
    }





    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This())) {
        return;
      }

      IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This())) {
        return;
      }

      IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This())) {
        return;
      }

      IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          IGameController *wrapper = IGameController::Unwrap<IGameController>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::IGameController^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapIGameController(::Windows::Gaming::Input::IGameController^ wintRtInstance);
      friend ::Windows::Gaming::Input::IGameController^ UnwrapIGameController(Local<Value> value);
  };

  Persistent<FunctionTemplate> IGameController::s_constructorTemplate;

  v8::Local<v8::Value> WrapIGameController(::Windows::Gaming::Input::IGameController^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(IGameController::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::IGameController^ UnwrapIGameController(Local<Value> value) {
     return IGameController::Unwrap<IGameController>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitIGameController(Local<Object> exports) {
    IGameController::Init(exports);
  }

  class IGameControllerBatteryInfo : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("IGameControllerBatteryInfo").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          




        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("IGameControllerBatteryInfo").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      IGameControllerBatteryInfo(::Windows::Gaming::Input::IGameControllerBatteryInfo^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::IGameControllerBatteryInfo^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameControllerBatteryInfo^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::IGameControllerBatteryInfo^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      IGameControllerBatteryInfo *wrapperInstance = new IGameControllerBatteryInfo(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameControllerBatteryInfo^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::IGameControllerBatteryInfo^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::IGameControllerBatteryInfo^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapIGameControllerBatteryInfo(winRtInstance));
    }


    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameControllerBatteryInfo^>(info.This())) {
        return;
      }

      IGameControllerBatteryInfo *wrapper = IGameControllerBatteryInfo::Unwrap<IGameControllerBatteryInfo>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }





    private:
      ::Windows::Gaming::Input::IGameControllerBatteryInfo^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapIGameControllerBatteryInfo(::Windows::Gaming::Input::IGameControllerBatteryInfo^ wintRtInstance);
      friend ::Windows::Gaming::Input::IGameControllerBatteryInfo^ UnwrapIGameControllerBatteryInfo(Local<Value> value);
  };

  Persistent<FunctionTemplate> IGameControllerBatteryInfo::s_constructorTemplate;

  v8::Local<v8::Value> WrapIGameControllerBatteryInfo(::Windows::Gaming::Input::IGameControllerBatteryInfo^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(IGameControllerBatteryInfo::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::IGameControllerBatteryInfo^ UnwrapIGameControllerBatteryInfo(Local<Value> value) {
     return IGameControllerBatteryInfo::Unwrap<IGameControllerBatteryInfo>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitIGameControllerBatteryInfo(Local<Object> exports) {
    IGameControllerBatteryInfo::Init(exports);
  }

  class RacingWheel : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("RacingWheel").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getButtonLabel", GetButtonLabel);
            Nan::SetPrototypeMethod(localRef, "getCurrentReading", GetCurrentReading);
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          


          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("hasClutch").ToLocalChecked(), HasClutchGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("hasHandbrake").ToLocalChecked(), HasHandbrakeGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("hasPatternShifter").ToLocalChecked(), HasPatternShifterGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("maxPatternShifterGear").ToLocalChecked(), MaxPatternShifterGearGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("maxWheelAngle").ToLocalChecked(), MaxWheelAngleGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("wheelMotor").ToLocalChecked(), WheelMotorGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "fromGameController", FromGameController);
        Nan::SetAccessor(constructor, Nan::New<String>("racingWheels").ToLocalChecked(), RacingWheelsGetter);
        


        Nan::Set(exports, Nan::New<String>("RacingWheel").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      RacingWheel(::Windows::Gaming::Input::RacingWheel^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::RacingWheel^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::RacingWheel^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      RacingWheel *wrapperInstance = new RacingWheel(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::RacingWheel^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::RacingWheel^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapRacingWheel(winRtInstance));
    }


    static void GetButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::Gaming::Input::RacingWheelButtons arg0 = static_cast<::Windows::Gaming::Input::RacingWheelButtons>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetCurrentReading(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Gaming::Input::RacingWheelReading result;
          result = wrapper->_instance->GetCurrentReading();
          info.GetReturnValue().Set(RacingWheelReadingToJsObject(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void FromGameController(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0]))
      {
        try
        {
          ::Windows::Gaming::Input::IGameController^ arg0 = UnwrapIGameController(info[0]);
          
          ::Windows::Gaming::Input::RacingWheel^ result;
          result = ::Windows::Gaming::Input::RacingWheel::FromGameController(arg0);
          info.GetReturnValue().Set(WrapRacingWheel(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HasClutchGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        bool result = wrapper->_instance->HasClutch;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HasHandbrakeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        bool result = wrapper->_instance->HasHandbrake;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HasPatternShifterGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        bool result = wrapper->_instance->HasPatternShifter;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MaxPatternShifterGearGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        int result = wrapper->_instance->MaxPatternShifterGear;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MaxWheelAngleGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        double result = wrapper->_instance->MaxWheelAngle;
        info.GetReturnValue().Set(Nan::New<Number>(static_cast<double>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void WheelMotorGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This())) {
        return;
      }

      RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());

      try  {
        ::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^ result = wrapper->_instance->WheelMotor;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Gaming.Input.ForceFeedback", "ForceFeedbackMotor", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void RacingWheelsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      try
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::RacingWheel^>^ result = ::Windows::Gaming::Input::RacingWheel::RacingWheels;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::RacingWheel^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::RacingWheel^ val) -> Local<Value> {
              return WrapRacingWheel(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::RacingWheel^ {
              return UnwrapRacingWheel(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      

    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"racingWheelAdded", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::RacingWheel::RacingWheelAdded::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::RacingWheel^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::RacingWheel^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapRacingWheel(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"racingWheelRemoved", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::RacingWheel::RacingWheelRemoved::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::RacingWheel^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::RacingWheel^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapRacingWheel(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"racingWheelAdded", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"racingWheelRemoved", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RacingWheel^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          RacingWheel *wrapper = RacingWheel::Unwrap<RacingWheel>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"racingWheelAdded", str))
        {
          ::Windows::Gaming::Input::RacingWheel::RacingWheelAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"racingWheelRemoved", str))
        {
          ::Windows::Gaming::Input::RacingWheel::RacingWheelRemoved::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::RacingWheel^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapRacingWheel(::Windows::Gaming::Input::RacingWheel^ wintRtInstance);
      friend ::Windows::Gaming::Input::RacingWheel^ UnwrapRacingWheel(Local<Value> value);
  };

  Persistent<FunctionTemplate> RacingWheel::s_constructorTemplate;

  v8::Local<v8::Value> WrapRacingWheel(::Windows::Gaming::Input::RacingWheel^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(RacingWheel::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::RacingWheel^ UnwrapRacingWheel(Local<Value> value) {
     return RacingWheel::Unwrap<RacingWheel>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitRacingWheel(Local<Object> exports) {
    RacingWheel::Init(exports);
  }

  class RawGameController : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("RawGameController").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getButtonLabel", GetButtonLabel);
            Nan::SetPrototypeMethod(localRef, "getCurrentReading", GetCurrentReading);
            Nan::SetPrototypeMethod(localRef, "getSwitchKind", GetSwitchKind);
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          


          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("axisCount").ToLocalChecked(), AxisCountGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("buttonCount").ToLocalChecked(), ButtonCountGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("forceFeedbackMotors").ToLocalChecked(), ForceFeedbackMotorsGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("hardwareProductId").ToLocalChecked(), HardwareProductIdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("hardwareVendorId").ToLocalChecked(), HardwareVendorIdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("switchCount").ToLocalChecked(), SwitchCountGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("displayName").ToLocalChecked(), DisplayNameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("nonRoamableId").ToLocalChecked(), NonRoamableIdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("simpleHapticsControllers").ToLocalChecked(), SimpleHapticsControllersGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "fromGameController", FromGameController);
        Nan::SetAccessor(constructor, Nan::New<String>("rawGameControllers").ToLocalChecked(), RawGameControllersGetter);
        


        Nan::Set(exports, Nan::New<String>("RawGameController").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      RawGameController(::Windows::Gaming::Input::RawGameController^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::RawGameController^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::RawGameController^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      RawGameController *wrapperInstance = new RawGameController(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::RawGameController^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::RawGameController^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapRawGameController(winRtInstance));
    }


    static void GetButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          int arg0 = static_cast<int>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetCurrentReading(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Not implemented")));
    }
    static void GetSwitchKind(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          int arg0 = static_cast<int>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerSwitchKind result;
          result = wrapper->_instance->GetSwitchKind(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void FromGameController(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0]))
      {
        try
        {
          ::Windows::Gaming::Input::IGameController^ arg0 = UnwrapIGameController(info[0]);
          
          ::Windows::Gaming::Input::RawGameController^ result;
          result = ::Windows::Gaming::Input::RawGameController::FromGameController(arg0);
          info.GetReturnValue().Set(WrapRawGameController(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void AxisCountGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        int result = wrapper->_instance->AxisCount;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void ButtonCountGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        int result = wrapper->_instance->ButtonCount;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void ForceFeedbackMotorsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^>^ result = wrapper->_instance->ForceFeedbackMotors;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^ val) -> Local<Value> {
              return NodeRT::Utils::CreateExternalWinRTObject("Windows.Gaming.Input.ForceFeedback", "ForceFeedbackMotor", val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^ {
              return dynamic_cast<::Windows::Gaming::Input::ForceFeedback::ForceFeedbackMotor^>(NodeRT::Utils::GetObjectInstance(value));
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HardwareProductIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        unsigned short result = wrapper->_instance->HardwareProductId;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HardwareVendorIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        unsigned short result = wrapper->_instance->HardwareVendorId;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SwitchCountGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        int result = wrapper->_instance->SwitchCount;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void DisplayNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->DisplayName;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void NonRoamableIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->NonRoamableId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SimpleHapticsControllersGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This())) {
        return;
      }

      RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());

      try  {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Devices::Haptics::SimpleHapticsController^>^ result = wrapper->_instance->SimpleHapticsControllers;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Devices::Haptics::SimpleHapticsController^>::CreateVectorViewWrapper(result, 
            [](::Windows::Devices::Haptics::SimpleHapticsController^ val) -> Local<Value> {
              return NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Haptics", "SimpleHapticsController", val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Devices::Haptics::SimpleHapticsController^>(value);
            },
            [](Local<Value> value) -> ::Windows::Devices::Haptics::SimpleHapticsController^ {
              return dynamic_cast<::Windows::Devices::Haptics::SimpleHapticsController^>(NodeRT::Utils::GetObjectInstance(value));
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void RawGameControllersGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      try
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::RawGameController^>^ result = ::Windows::Gaming::Input::RawGameController::RawGameControllers;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::RawGameController^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::RawGameController^ val) -> Local<Value> {
              return WrapRawGameController(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::RawGameController^ {
              return UnwrapRawGameController(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      

    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"rawGameControllerAdded", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::RawGameController::RawGameControllerAdded::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::RawGameController^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::RawGameController^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapRawGameController(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"rawGameControllerRemoved", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::RawGameController::RawGameControllerRemoved::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::RawGameController^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::RawGameController^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapRawGameController(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"rawGameControllerAdded", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"rawGameControllerRemoved", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::RawGameController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          RawGameController *wrapper = RawGameController::Unwrap<RawGameController>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"rawGameControllerAdded", str))
        {
          ::Windows::Gaming::Input::RawGameController::RawGameControllerAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"rawGameControllerRemoved", str))
        {
          ::Windows::Gaming::Input::RawGameController::RawGameControllerRemoved::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::RawGameController^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapRawGameController(::Windows::Gaming::Input::RawGameController^ wintRtInstance);
      friend ::Windows::Gaming::Input::RawGameController^ UnwrapRawGameController(Local<Value> value);
  };

  Persistent<FunctionTemplate> RawGameController::s_constructorTemplate;

  v8::Local<v8::Value> WrapRawGameController(::Windows::Gaming::Input::RawGameController^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(RawGameController::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::RawGameController^ UnwrapRawGameController(Local<Value> value) {
     return RawGameController::Unwrap<RawGameController>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitRawGameController(Local<Object> exports) {
    RawGameController::Init(exports);
  }

  class UINavigationController : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("UINavigationController").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getCurrentReading", GetCurrentReading);
            Nan::SetPrototypeMethod(localRef, "getOptionalButtonLabel", GetOptionalButtonLabel);
            Nan::SetPrototypeMethod(localRef, "getRequiredButtonLabel", GetRequiredButtonLabel);
            Nan::SetPrototypeMethod(localRef, "tryGetBatteryReport", TryGetBatteryReport);
          


          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("headset").ToLocalChecked(), HeadsetGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isWireless").ToLocalChecked(), IsWirelessGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("user").ToLocalChecked(), UserGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "fromGameController", FromGameController);
        Nan::SetAccessor(constructor, Nan::New<String>("uINavigationControllers").ToLocalChecked(), UINavigationControllersGetter);
        


        Nan::Set(exports, Nan::New<String>("UINavigationController").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      UINavigationController(::Windows::Gaming::Input::UINavigationController^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Gaming::Input::UINavigationController^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info[0])) {
        try {
          winRtInstance = (::Windows::Gaming::Input::UINavigationController^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      UINavigationController *wrapperInstance = new UINavigationController(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Gaming::Input::UINavigationController^ winRtInstance;
      try {
        winRtInstance = (::Windows::Gaming::Input::UINavigationController^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapUINavigationController(winRtInstance));
    }


    static void GetCurrentReading(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Gaming::Input::UINavigationReading result;
          result = wrapper->_instance->GetCurrentReading();
          info.GetReturnValue().Set(UINavigationReadingToJsObject(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetOptionalButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::Gaming::Input::OptionalUINavigationButtons arg0 = static_cast<::Windows::Gaming::Input::OptionalUINavigationButtons>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetOptionalButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void GetRequiredButtonLabel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::Gaming::Input::RequiredUINavigationButtons arg0 = static_cast<::Windows::Gaming::Input::RequiredUINavigationButtons>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          ::Windows::Gaming::Input::GameControllerButtonLabel result;
          result = wrapper->_instance->GetRequiredButtonLabel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }
    static void TryGetBatteryReport(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Devices::Power::BatteryReport^ result;
          result = wrapper->_instance->TryGetBatteryReport();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Power", "BatteryReport", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void FromGameController(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::IGameController^>(info[0]))
      {
        try
        {
          ::Windows::Gaming::Input::IGameController^ arg0 = UnwrapIGameController(info[0]);
          
          ::Windows::Gaming::Input::UINavigationController^ result;
          result = ::Windows::Gaming::Input::UINavigationController::FromGameController(arg0);
          info.GetReturnValue().Set(WrapUINavigationController(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void HeadsetGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      try  {
        ::Windows::Gaming::Input::Headset^ result = wrapper->_instance->Headset;
        info.GetReturnValue().Set(WrapHeadset(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsWirelessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      try  {
        bool result = wrapper->_instance->IsWireless;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void UserGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This())) {
        return;
      }

      UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());

      try  {
        ::Windows::System::User^ result = wrapper->_instance->User;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "User", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void UINavigationControllersGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      try
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Gaming::Input::UINavigationController^>^ result = ::Windows::Gaming::Input::UINavigationController::UINavigationControllers;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Gaming::Input::UINavigationController^>::CreateVectorViewWrapper(result, 
            [](::Windows::Gaming::Input::UINavigationController^ val) -> Local<Value> {
              return WrapUINavigationController(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(value);
            },
            [](Local<Value> value) -> ::Windows::Gaming::Input::UINavigationController^ {
              return UnwrapUINavigationController(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      

    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetConnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->HeadsetDisconnected::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::Gaming::Input::Headset^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::Gaming::Input::Headset^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = WrapHeadset(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->UserChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Gaming::Input::IGameController^, ::Windows::System::UserChangedEventArgs^>(
            [callbackObjPtr](::Windows::Gaming::Input::IGameController^ arg0, ::Windows::System::UserChangedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapIGameController(arg0);
                  wrappedArg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.System", "UserChangedEventArgs", arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"uINavigationControllerAdded", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::UINavigationController::UINavigationControllerAdded::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::UINavigationController^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::UINavigationController^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapUINavigationController(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
      else if (NodeRT::Utils::CaseInsenstiveEquals(L"uINavigationControllerRemoved", str))
      {
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = ::Windows::Gaming::Input::UINavigationController::UINavigationControllerRemoved::add(
            ref new ::Windows::Foundation::EventHandler<::Windows::Gaming::Input::UINavigationController^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Windows::Gaming::Input::UINavigationController^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = CreateOpaqueWrapper(arg0);
                  wrappedArg1 = WrapUINavigationController(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"uINavigationControllerAdded", str)) &&(!NodeRT::Utils::CaseInsenstiveEquals(L"uINavigationControllerRemoved", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetConnected", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());
          wrapper->_instance->HeadsetConnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"headsetDisconnected", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());
          wrapper->_instance->HeadsetDisconnected::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"userChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Gaming::Input::UINavigationController^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          UINavigationController *wrapper = UINavigationController::Unwrap<UINavigationController>(info.This());
          wrapper->_instance->UserChanged::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"uINavigationControllerAdded", str))
        {
          ::Windows::Gaming::Input::UINavigationController::UINavigationControllerAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"uINavigationControllerRemoved", str))
        {
          ::Windows::Gaming::Input::UINavigationController::UINavigationControllerRemoved::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Gaming::Input::UINavigationController^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapUINavigationController(::Windows::Gaming::Input::UINavigationController^ wintRtInstance);
      friend ::Windows::Gaming::Input::UINavigationController^ UnwrapUINavigationController(Local<Value> value);
  };

  Persistent<FunctionTemplate> UINavigationController::s_constructorTemplate;

  v8::Local<v8::Value> WrapUINavigationController(::Windows::Gaming::Input::UINavigationController^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(UINavigationController::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Gaming::Input::UINavigationController^ UnwrapUINavigationController(Local<Value> value) {
     return UINavigationController::Unwrap<UINavigationController>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitUINavigationController(Local<Object> exports) {
    UINavigationController::Init(exports);
  }


} } } } 

NAN_MODULE_INIT(init) {
  // We ignore failures for now since it probably means that
  // the initialization already happened for STA, and that's cool

  CoInitializeEx(nullptr, COINIT_MULTITHREADED);

  /*
  if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
    Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"error in CoInitializeEx()")));
    return;
  }
  */

      NodeRT::Windows::Gaming::Input::InitArcadeStickButtonsEnum(target);
      NodeRT::Windows::Gaming::Input::InitFlightStickButtonsEnum(target);
      NodeRT::Windows::Gaming::Input::InitGameControllerButtonLabelEnum(target);
      NodeRT::Windows::Gaming::Input::InitGameControllerSwitchKindEnum(target);
      NodeRT::Windows::Gaming::Input::InitGameControllerSwitchPositionEnum(target);
      NodeRT::Windows::Gaming::Input::InitGamepadButtonsEnum(target);
      NodeRT::Windows::Gaming::Input::InitOptionalUINavigationButtonsEnum(target);
      NodeRT::Windows::Gaming::Input::InitRacingWheelButtonsEnum(target);
      NodeRT::Windows::Gaming::Input::InitRequiredUINavigationButtonsEnum(target);
      NodeRT::Windows::Gaming::Input::InitArcadeStick(target);
      NodeRT::Windows::Gaming::Input::InitFlightStick(target);
      NodeRT::Windows::Gaming::Input::InitGamepad(target);
      NodeRT::Windows::Gaming::Input::InitHeadset(target);
      NodeRT::Windows::Gaming::Input::InitIGameController(target);
      NodeRT::Windows::Gaming::Input::InitIGameControllerBatteryInfo(target);
      NodeRT::Windows::Gaming::Input::InitRacingWheel(target);
      NodeRT::Windows::Gaming::Input::InitRawGameController(target);
      NodeRT::Windows::Gaming::Input::InitUINavigationController(target);


  NodeRT::Utils::RegisterNameSpace("Windows.Gaming.Input", target);
}



NODE_MODULE(binding, init)
