// Copyright (c) Microsoft Corporation
// 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::Handle;
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 ApplicationModel { namespace Calls { 

  v8::Local<v8::Value> WrapPhoneLine(::Windows::ApplicationModel::Calls::PhoneLine^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneLine^ UnwrapPhoneLine(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneVoicemail(::Windows::ApplicationModel::Calls::PhoneVoicemail^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneVoicemail^ UnwrapPhoneVoicemail(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneLineCellularDetails(::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ UnwrapPhoneLineCellularDetails(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallVideoCapabilities(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ UnwrapPhoneCallVideoCapabilities(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneLineConfiguration(::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ UnwrapPhoneLineConfiguration(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneDialOptions(::Windows::ApplicationModel::Calls::PhoneDialOptions^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneDialOptions^ UnwrapPhoneDialOptions(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneLineWatcher(::Windows::ApplicationModel::Calls::PhoneLineWatcher^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneLineWatcher^ UnwrapPhoneLineWatcher(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneLineWatcherEventArgs(::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ UnwrapPhoneLineWatcherEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallStore(::Windows::ApplicationModel::Calls::PhoneCallStore^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallStore^ UnwrapPhoneCallStore(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallManager(::Windows::ApplicationModel::Calls::PhoneCallManager^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallManager^ UnwrapPhoneCallManager(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallVideoCapabilitiesManager(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ UnwrapPhoneCallVideoCapabilitiesManager(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallBlocking(::Windows::ApplicationModel::Calls::PhoneCallBlocking^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallBlocking^ UnwrapPhoneCallBlocking(Local<Value> value);
  
  v8::Local<v8::Value> WrapCallStateChangeEventArgs(::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ UnwrapCallStateChangeEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapCallAnswerEventArgs(::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ UnwrapCallAnswerEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapCallRejectEventArgs(::Windows::ApplicationModel::Calls::CallRejectEventArgs^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::CallRejectEventArgs^ UnwrapCallRejectEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapVoipPhoneCall(::Windows::ApplicationModel::Calls::VoipPhoneCall^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::VoipPhoneCall^ UnwrapVoipPhoneCall(Local<Value> value);
  
  v8::Local<v8::Value> WrapMuteChangeEventArgs(::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ UnwrapMuteChangeEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapVoipCallCoordinator(::Windows::ApplicationModel::Calls::VoipCallCoordinator^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::VoipCallCoordinator^ UnwrapVoipCallCoordinator(Local<Value> value);
  
  v8::Local<v8::Value> WrapLockScreenCallEndCallDeferral(::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ UnwrapLockScreenCallEndCallDeferral(Local<Value> value);
  
  v8::Local<v8::Value> WrapLockScreenCallUI(::Windows::ApplicationModel::Calls::LockScreenCallUI^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::LockScreenCallUI^ UnwrapLockScreenCallUI(Local<Value> value);
  
  v8::Local<v8::Value> WrapLockScreenCallEndRequestedEventArgs(::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ UnwrapLockScreenCallEndRequestedEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallHistoryEntryAddress(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ UnwrapPhoneCallHistoryEntryAddress(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallHistoryEntry(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ UnwrapPhoneCallHistoryEntry(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallHistoryEntryReader(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ UnwrapPhoneCallHistoryEntryReader(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallHistoryEntryQueryOptions(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ UnwrapPhoneCallHistoryEntryQueryOptions(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallHistoryStore(::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ UnwrapPhoneCallHistoryStore(Local<Value> value);
  
  v8::Local<v8::Value> WrapPhoneCallHistoryManager(::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ wintRtInstance);
  ::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ UnwrapPhoneCallHistoryManager(Local<Value> value);
  


  static void InitPhoneNetworkStateEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneNetworkState").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("unknown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::Unknown)));
	Nan::Set(enumObject, Nan::New<String>("noSignal").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::NoSignal)));
	Nan::Set(enumObject, Nan::New<String>("deregistered").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::Deregistered)));
	Nan::Set(enumObject, Nan::New<String>("denied").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::Denied)));
	Nan::Set(enumObject, Nan::New<String>("searching").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::Searching)));
	Nan::Set(enumObject, Nan::New<String>("home").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::Home)));
	Nan::Set(enumObject, Nan::New<String>("roamingInternational").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::RoamingInternational)));
	Nan::Set(enumObject, Nan::New<String>("roamingDomestic").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneNetworkState::RoamingDomestic)));
  }


  static void InitPhoneVoicemailTypeEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneVoicemailType").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneVoicemailType::None)));
	Nan::Set(enumObject, Nan::New<String>("traditional").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneVoicemailType::Traditional)));
	Nan::Set(enumObject, Nan::New<String>("visual").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneVoicemailType::Visual)));
  }


  static void InitPhoneCallMediaEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallMedia").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("audio").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallMedia::Audio)));
	Nan::Set(enumObject, Nan::New<String>("audioAndVideo").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallMedia::AudioAndVideo)));
  }


  static void InitPhoneLineTransportEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneLineTransport").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("cellular").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineTransport::Cellular)));
	Nan::Set(enumObject, Nan::New<String>("voipApp").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineTransport::VoipApp)));
  }


  static void InitPhoneSimStateEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneSimState").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("unknown").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::Unknown)));
	Nan::Set(enumObject, Nan::New<String>("pinNotRequired").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::PinNotRequired)));
	Nan::Set(enumObject, Nan::New<String>("pinUnlocked").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::PinUnlocked)));
	Nan::Set(enumObject, Nan::New<String>("pinLocked").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::PinLocked)));
	Nan::Set(enumObject, Nan::New<String>("pukLocked").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::PukLocked)));
	Nan::Set(enumObject, Nan::New<String>("notInserted").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::NotInserted)));
	Nan::Set(enumObject, Nan::New<String>("invalid").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::Invalid)));
	Nan::Set(enumObject, Nan::New<String>("disabled").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneSimState::Disabled)));
  }


  static void InitPhoneAudioRoutingEndpointEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneAudioRoutingEndpoint").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("default").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneAudioRoutingEndpoint::Default)));
	Nan::Set(enumObject, Nan::New<String>("bluetooth").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneAudioRoutingEndpoint::Bluetooth)));
	Nan::Set(enumObject, Nan::New<String>("speakerphone").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneAudioRoutingEndpoint::Speakerphone)));
  }


  static void InitPhoneLineWatcherStatusEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneLineWatcherStatus").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("created").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineWatcherStatus::Created)));
	Nan::Set(enumObject, Nan::New<String>("started").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineWatcherStatus::Started)));
	Nan::Set(enumObject, Nan::New<String>("enumerationCompleted").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineWatcherStatus::EnumerationCompleted)));
	Nan::Set(enumObject, Nan::New<String>("stopped").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineWatcherStatus::Stopped)));
  }


  static void InitPhoneLineNetworkOperatorDisplayTextLocationEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneLineNetworkOperatorDisplayTextLocation").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("default").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineNetworkOperatorDisplayTextLocation::Default)));
	Nan::Set(enumObject, Nan::New<String>("tile").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineNetworkOperatorDisplayTextLocation::Tile)));
	Nan::Set(enumObject, Nan::New<String>("dialer").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineNetworkOperatorDisplayTextLocation::Dialer)));
	Nan::Set(enumObject, Nan::New<String>("inCallUI").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneLineNetworkOperatorDisplayTextLocation::InCallUI)));
  }


  static void InitCellularDtmfModeEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("CellularDtmfMode").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("continuous").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::CellularDtmfMode::Continuous)));
	Nan::Set(enumObject, Nan::New<String>("burst").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::CellularDtmfMode::Burst)));
  }


  static void InitVoipPhoneCallMediaEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("VoipPhoneCallMedia").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallMedia::None)));
	Nan::Set(enumObject, Nan::New<String>("audio").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallMedia::Audio)));
	Nan::Set(enumObject, Nan::New<String>("video").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallMedia::Video)));
  }


  static void InitVoipPhoneCallRejectReasonEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("VoipPhoneCallRejectReason").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("userIgnored").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallRejectReason::UserIgnored)));
	Nan::Set(enumObject, Nan::New<String>("timedOut").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallRejectReason::TimedOut)));
	Nan::Set(enumObject, Nan::New<String>("otherIncomingCall").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallRejectReason::OtherIncomingCall)));
	Nan::Set(enumObject, Nan::New<String>("emergencyCallExists").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallRejectReason::EmergencyCallExists)));
	Nan::Set(enumObject, Nan::New<String>("invalidCallState").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallRejectReason::InvalidCallState)));
  }


  static void InitVoipPhoneCallStateEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("VoipPhoneCallState").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("ended").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallState::Ended)));
	Nan::Set(enumObject, Nan::New<String>("held").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallState::Held)));
	Nan::Set(enumObject, Nan::New<String>("active").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallState::Active)));
	Nan::Set(enumObject, Nan::New<String>("incoming").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallState::Incoming)));
	Nan::Set(enumObject, Nan::New<String>("outgoing").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallState::Outgoing)));
  }


  static void InitVoipPhoneCallResourceReservationStatusEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("VoipPhoneCallResourceReservationStatus").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("success").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallResourceReservationStatus::Success)));
	Nan::Set(enumObject, Nan::New<String>("resourcesNotAvailable").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::VoipPhoneCallResourceReservationStatus::ResourcesNotAvailable)));
  }


  static void InitPhoneCallHistoryEntryOtherAppReadAccessEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryOtherAppReadAccess").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("full").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryOtherAppReadAccess::Full)));
	Nan::Set(enumObject, Nan::New<String>("systemOnly").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryOtherAppReadAccess::SystemOnly)));
  }


  static void InitPhoneCallHistoryEntryMediaEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryMedia").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("audio").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryMedia::Audio)));
	Nan::Set(enumObject, Nan::New<String>("video").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryMedia::Video)));
  }


  static void InitPhoneCallHistoryEntryRawAddressKindEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryRawAddressKind").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("phoneNumber").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind::PhoneNumber)));
	Nan::Set(enumObject, Nan::New<String>("custom").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind::Custom)));
  }


  static void InitPhoneCallHistoryEntryQueryDesiredMediaEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryQueryDesiredMedia").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("none").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia::None)));
	Nan::Set(enumObject, Nan::New<String>("audio").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia::Audio)));
	Nan::Set(enumObject, Nan::New<String>("video").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia::Video)));
	Nan::Set(enumObject, Nan::New<String>("all").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia::All)));
  }


  static void InitPhoneCallHistoryStoreAccessTypeEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallHistoryStoreAccessType").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("appEntriesReadWrite").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryStoreAccessType::AppEntriesReadWrite)));
	Nan::Set(enumObject, Nan::New<String>("allEntriesLimitedReadWrite").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryStoreAccessType::AllEntriesLimitedReadWrite)));
	Nan::Set(enumObject, Nan::New<String>("allEntriesReadWrite").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistoryStoreAccessType::AllEntriesReadWrite)));
  }


  static void InitPhoneCallHistorySourceIdKindEnum(const Local<Object> exports)
  {
    HandleScope scope;
    
	Local<Object> enumObject = Nan::New<Object>();
    Nan::Set(exports, Nan::New<String>("PhoneCallHistorySourceIdKind").ToLocalChecked(), enumObject);
	Nan::Set(enumObject, Nan::New<String>("cellularPhoneLineId").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistorySourceIdKind::CellularPhoneLineId)));
	Nan::Set(enumObject, Nan::New<String>("packageFamilyName").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::ApplicationModel::Calls::PhoneCallHistorySourceIdKind::PackageFamilyName)));
  }



  
  static bool IsCallsPhoneContractJsObject(Local<Value> value)
  {
    if (!value->IsObject())
    {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    return true;
  }

  ::Windows::ApplicationModel::Calls::CallsPhoneContract CallsPhoneContractFromJsObject(Local<Value> value)
  {
    HandleScope scope;
    ::Windows::ApplicationModel::Calls::CallsPhoneContract 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> CallsPhoneContractToJsObject(::Windows::ApplicationModel::Calls::CallsPhoneContract value)
  {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    
    return scope.Escape(obj);
  }

  
  static bool IsCallsVoipContractJsObject(Local<Value> value)
  {
    if (!value->IsObject())
    {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    return true;
  }

  ::Windows::ApplicationModel::Calls::CallsVoipContract CallsVoipContractFromJsObject(Local<Value> value)
  {
    HandleScope scope;
    ::Windows::ApplicationModel::Calls::CallsVoipContract 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> CallsVoipContractToJsObject(::Windows::ApplicationModel::Calls::CallsVoipContract value)
  {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    
    return scope.Escape(obj);
  }

  
  static bool IsLockScreenCallContractJsObject(Local<Value> value)
  {
    if (!value->IsObject())
    {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    return true;
  }

  ::Windows::ApplicationModel::Calls::LockScreenCallContract LockScreenCallContractFromJsObject(Local<Value> value)
  {
    HandleScope scope;
    ::Windows::ApplicationModel::Calls::LockScreenCallContract 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> LockScreenCallContractToJsObject(::Windows::ApplicationModel::Calls::LockScreenCallContract value)
  {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    
    return scope.Escape(obj);
  }

  
  static bool IsColorJsObject(Local<Value> value)
  {
    if (!value->IsObject())
    {
      return false;
    }

    Local<String> symbol;
    Local<Object> obj = Nan::To<Object>(value).ToLocalChecked();

    return true;
  }

  ::Windows::UI::Color ColorFromJsObject(Local<Value> value)
  {
    HandleScope scope;
    ::Windows::UI::Color 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> ColorToJsObject(::Windows::UI::Color value)
  {
    EscapableHandleScope scope;

    Local<Object> obj = Nan::New<Object>();

    
    return scope.Escape(obj);
  }

  
  class PhoneLine : 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>("PhoneLine").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
            
      Nan::SetPrototypeMethod(localRef, "dial", Dial);
      Nan::SetPrototypeMethod(localRef, "dialWithOptions", DialWithOptions);
      
            
      Nan::SetPrototypeMethod(localRef, "isImmediateDialNumberAsync", IsImmediateDialNumberAsync);
      
            
      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>("canDial").ToLocalChecked(), CanDialGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("cellularDetails").ToLocalChecked(), CellularDetailsGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("displayColor").ToLocalChecked(), DisplayColorGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("displayName").ToLocalChecked(), DisplayNameGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("id").ToLocalChecked(), IdGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("lineConfiguration").ToLocalChecked(), LineConfigurationGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("networkName").ToLocalChecked(), NetworkNameGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("networkState").ToLocalChecked(), NetworkStateGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("supportsTile").ToLocalChecked(), SupportsTileGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("transport").ToLocalChecked(), TransportGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoCallingCapabilities").ToLocalChecked(), VideoCallingCapabilitiesGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("voicemail").ToLocalChecked(), VoicemailGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);

      func = Nan::GetFunction(Nan::New<FunctionTemplate>(FromIdAsync)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("fromIdAsync").ToLocalChecked(), func);

      Nan::Set(exports, Nan::New<String>("PhoneLine").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneLine(::Windows::ApplicationModel::Calls::PhoneLine^ 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::ApplicationModel::Calls::PhoneLine^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLine^) 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());

      PhoneLine *wrapperInstance = new PhoneLine(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::ApplicationModel::Calls::PhoneLine^>(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::ApplicationModel::Calls::PhoneLine^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLine^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneLine(winRtInstance));
    }


    static void IsImmediateDialNumberAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      ::Windows::Foundation::IAsyncOperation<bool>^ op;
    

      if (info.Length() == 2
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          
          op = wrapper->_instance->IsImmediateDialNumberAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<bool> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = Nan::New<Boolean>(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
  
    static void Dial(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      if (info.Length() == 2
        && info[0]->IsString()
        && info[1]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[1])));
          
          wrapper->_instance->Dial(arg0, arg1);
          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 DialWithOptions(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info[0]))
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneDialOptions^ arg0 = UnwrapPhoneDialOptions(info[0]);
          
          wrapper->_instance->DialWithOptions(arg0);
          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 FromIdAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::ApplicationModel::Calls::PhoneLine^>^ op;
      

      if (info.Length() == 2
        && NodeRT::Utils::IsGuid(info[0]))
      {
        try
        {
          ::Platform::Guid arg0 = NodeRT::Utils::GuidFromJs(info[0]);
          
          op = ::Windows::ApplicationModel::Calls::PhoneLine::FromIdAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::ApplicationModel::Calls::PhoneLine^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = WrapPhoneLine(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

	  	    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }


    static void CanDialGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        bool result = wrapper->_instance->CanDial;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void CellularDetailsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ result = wrapper->_instance->CellularDetails;
        info.GetReturnValue().Set(WrapPhoneLineCellularDetails(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void DisplayColorGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::UI::Color result = wrapper->_instance->DisplayColor;
        info.GetReturnValue().Set(NodeRT::Utils::ColorToJs(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::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(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 IdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Platform::Guid result = wrapper->_instance->Id;
        info.GetReturnValue().Set(NodeRT::Utils::GuidToJs(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void LineConfigurationGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ result = wrapper->_instance->LineConfiguration;
        info.GetReturnValue().Set(WrapPhoneLineConfiguration(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void NetworkNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->NetworkName;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void NetworkStateGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneNetworkState result = wrapper->_instance->NetworkState;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void SupportsTileGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        bool result = wrapper->_instance->SupportsTile;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void TransportGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneLineTransport result = wrapper->_instance->Transport;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void VideoCallingCapabilitiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ result = wrapper->_instance->VideoCallingCapabilities;
        info.GetReturnValue().Set(WrapPhoneCallVideoCapabilities(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void VoicemailGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(info.This()))
      {
        return;
      }

      PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneVoicemail^ result = wrapper->_instance->Voicemail;
        info.GetReturnValue().Set(WrapPhoneVoicemail(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(info[0]);
      auto str = *eventName;
      
      Local<Function> callback = info[1].As<Function>();
      
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"lineChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(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;
        }
        PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(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->LineChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::PhoneLine^, ::Platform::Object^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::PhoneLine^ arg0, ::Platform::Object^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapPhoneLine(arg0);
                Local<Value> wrappedArg1 = CreateOpaqueWrapper(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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(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(info[0]);
      auto str = *eventName;

      if ((NodeRT::Utils::CaseInsenstiveEquals(L"lineChanged", str)))
      {
        Nan::ThrowError(Nan::Error(String::Concat(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"lineChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLine^>(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;
          }
          PhoneLine *wrapper = PhoneLine::Unwrap<PhoneLine>(info.This());
          wrapper->_instance->LineChanged::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::ApplicationModel::Calls::PhoneLine^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneLine(::Windows::ApplicationModel::Calls::PhoneLine^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneLine^ UnwrapPhoneLine(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneLine::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneLine(::Windows::ApplicationModel::Calls::PhoneLine^ 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>(PhoneLine::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneLine^ UnwrapPhoneLine(Local<Value> value)
  {
     return PhoneLine::Unwrap<PhoneLine>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneLine(Local<Object> exports)
  {
    PhoneLine::Init(exports);
  }

  class PhoneVoicemail : 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>("PhoneVoicemail").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
                  
      Nan::SetPrototypeMethod(localRef, "dialVoicemailAsync", DialVoicemailAsync);
      
                  
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("messageCount").ToLocalChecked(), MessageCountGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("number").ToLocalChecked(), NumberGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("type").ToLocalChecked(), TypeGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneVoicemail").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneVoicemail(::Windows::ApplicationModel::Calls::PhoneVoicemail^ 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::ApplicationModel::Calls::PhoneVoicemail^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneVoicemail^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneVoicemail^) 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());

      PhoneVoicemail *wrapperInstance = new PhoneVoicemail(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::ApplicationModel::Calls::PhoneVoicemail^>(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::ApplicationModel::Calls::PhoneVoicemail^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneVoicemail^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneVoicemail(winRtInstance));
    }


    static void DialVoicemailAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneVoicemail^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneVoicemail *wrapper = PhoneVoicemail::Unwrap<PhoneVoicemail>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->DialVoicemailAsync();
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
  



    static void MessageCountGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneVoicemail^>(info.This()))
      {
        return;
      }

      PhoneVoicemail *wrapper = PhoneVoicemail::Unwrap<PhoneVoicemail>(info.This());

      try 
      {
        int result = wrapper->_instance->MessageCount;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void NumberGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneVoicemail^>(info.This()))
      {
        return;
      }

      PhoneVoicemail *wrapper = PhoneVoicemail::Unwrap<PhoneVoicemail>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->Number;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void TypeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneVoicemail^>(info.This()))
      {
        return;
      }

      PhoneVoicemail *wrapper = PhoneVoicemail::Unwrap<PhoneVoicemail>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneVoicemailType result = wrapper->_instance->Type;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneVoicemail^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneVoicemail(::Windows::ApplicationModel::Calls::PhoneVoicemail^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneVoicemail^ UnwrapPhoneVoicemail(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneVoicemail::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneVoicemail(::Windows::ApplicationModel::Calls::PhoneVoicemail^ 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>(PhoneVoicemail::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneVoicemail^ UnwrapPhoneVoicemail(Local<Value> value)
  {
     return PhoneVoicemail::Unwrap<PhoneVoicemail>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneVoicemail(Local<Object> exports)
  {
    PhoneVoicemail::Init(exports);
  }

  class PhoneLineCellularDetails : 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>("PhoneLineCellularDetails").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      Nan::SetPrototypeMethod(localRef, "getNetworkOperatorDisplayText", GetNetworkOperatorDisplayText);
      
                        
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isModemOn").ToLocalChecked(), IsModemOnGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("registrationRejectCode").ToLocalChecked(), RegistrationRejectCodeGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("simSlotIndex").ToLocalChecked(), SimSlotIndexGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("simState").ToLocalChecked(), SimStateGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneLineCellularDetails").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneLineCellularDetails(::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ 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::ApplicationModel::Calls::PhoneLineCellularDetails^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^) 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());

      PhoneLineCellularDetails *wrapperInstance = new PhoneLineCellularDetails(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::ApplicationModel::Calls::PhoneLineCellularDetails^>(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::ApplicationModel::Calls::PhoneLineCellularDetails^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneLineCellularDetails(winRtInstance));
    }


  
    static void GetNetworkOperatorDisplayText(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^>(info.This()))
      {
        return;
      }

      PhoneLineCellularDetails *wrapper = PhoneLineCellularDetails::Unwrap<PhoneLineCellularDetails>(info.This());

      if (info.Length() == 1
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneLineNetworkOperatorDisplayTextLocation arg0 = static_cast<::Windows::ApplicationModel::Calls::PhoneLineNetworkOperatorDisplayTextLocation>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          Platform::String^ result;
          result = wrapper->_instance->GetNetworkOperatorDisplayText(arg0);
          info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
          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 IsModemOnGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^>(info.This()))
      {
        return;
      }

      PhoneLineCellularDetails *wrapper = PhoneLineCellularDetails::Unwrap<PhoneLineCellularDetails>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsModemOn;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void RegistrationRejectCodeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^>(info.This()))
      {
        return;
      }

      PhoneLineCellularDetails *wrapper = PhoneLineCellularDetails::Unwrap<PhoneLineCellularDetails>(info.This());

      try 
      {
        int result = wrapper->_instance->RegistrationRejectCode;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void SimSlotIndexGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^>(info.This()))
      {
        return;
      }

      PhoneLineCellularDetails *wrapper = PhoneLineCellularDetails::Unwrap<PhoneLineCellularDetails>(info.This());

      try 
      {
        int result = wrapper->_instance->SimSlotIndex;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void SimStateGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^>(info.This()))
      {
        return;
      }

      PhoneLineCellularDetails *wrapper = PhoneLineCellularDetails::Unwrap<PhoneLineCellularDetails>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneSimState result = wrapper->_instance->SimState;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneLineCellularDetails(::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ UnwrapPhoneLineCellularDetails(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneLineCellularDetails::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneLineCellularDetails(::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ 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>(PhoneLineCellularDetails::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneLineCellularDetails^ UnwrapPhoneLineCellularDetails(Local<Value> value)
  {
     return PhoneLineCellularDetails::Unwrap<PhoneLineCellularDetails>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneLineCellularDetails(Local<Object> exports)
  {
    PhoneLineCellularDetails::Init(exports);
  }

  class PhoneCallVideoCapabilities : 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>("PhoneCallVideoCapabilities").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isVideoCallingCapable").ToLocalChecked(), IsVideoCallingCapableGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallVideoCapabilities").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallVideoCapabilities(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ 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::ApplicationModel::Calls::PhoneCallVideoCapabilities^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^) 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());

      PhoneCallVideoCapabilities *wrapperInstance = new PhoneCallVideoCapabilities(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::ApplicationModel::Calls::PhoneCallVideoCapabilities^>(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::ApplicationModel::Calls::PhoneCallVideoCapabilities^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallVideoCapabilities(winRtInstance));
    }


  



    static void IsVideoCallingCapableGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^>(info.This()))
      {
        return;
      }

      PhoneCallVideoCapabilities *wrapper = PhoneCallVideoCapabilities::Unwrap<PhoneCallVideoCapabilities>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsVideoCallingCapable;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallVideoCapabilities(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ UnwrapPhoneCallVideoCapabilities(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallVideoCapabilities::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallVideoCapabilities(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ 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>(PhoneCallVideoCapabilities::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^ UnwrapPhoneCallVideoCapabilities(Local<Value> value)
  {
     return PhoneCallVideoCapabilities::Unwrap<PhoneCallVideoCapabilities>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallVideoCapabilities(Local<Object> exports)
  {
    PhoneCallVideoCapabilities::Init(exports);
  }

  class PhoneLineConfiguration : 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>("PhoneLineConfiguration").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("extendedProperties").ToLocalChecked(), ExtendedPropertiesGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isVideoCallingEnabled").ToLocalChecked(), IsVideoCallingEnabledGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneLineConfiguration").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneLineConfiguration(::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ 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::ApplicationModel::Calls::PhoneLineConfiguration^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineConfiguration^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineConfiguration^) 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());

      PhoneLineConfiguration *wrapperInstance = new PhoneLineConfiguration(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::ApplicationModel::Calls::PhoneLineConfiguration^>(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::ApplicationModel::Calls::PhoneLineConfiguration^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineConfiguration^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneLineConfiguration(winRtInstance));
    }


  



    static void ExtendedPropertiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineConfiguration^>(info.This()))
      {
        return;
      }

      PhoneLineConfiguration *wrapper = PhoneLineConfiguration::Unwrap<PhoneLineConfiguration>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IMapView<::Platform::String^, ::Platform::Object^>^ result = wrapper->_instance->ExtendedProperties;
        info.GetReturnValue().Set(NodeRT::Collections::MapViewWrapper<::Platform::String^,::Platform::Object^>::CreateMapViewWrapper(result, 
            [](::Platform::String^ val) -> Local<Value> {
              return NodeRT::Utils::NewString(val->Data());
            },
            [](Local<Value> value) -> bool {
              return value->IsString();
            },
            [](Local<Value> value) -> ::Platform::String^ {
              return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
            },
            [](::Platform::Object^ val) -> Local<Value> {
              return CreateOpaqueWrapper(val);
            }
          ));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsVideoCallingEnabledGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineConfiguration^>(info.This()))
      {
        return;
      }

      PhoneLineConfiguration *wrapper = PhoneLineConfiguration::Unwrap<PhoneLineConfiguration>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsVideoCallingEnabled;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneLineConfiguration(::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ UnwrapPhoneLineConfiguration(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneLineConfiguration::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneLineConfiguration(::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ 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>(PhoneLineConfiguration::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneLineConfiguration^ UnwrapPhoneLineConfiguration(Local<Value> value)
  {
     return PhoneLineConfiguration::Unwrap<PhoneLineConfiguration>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneLineConfiguration(Local<Object> exports)
  {
    PhoneLineConfiguration::Init(exports);
  }

  class PhoneDialOptions : 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>("PhoneDialOptions").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("number").ToLocalChecked(), NumberGetter, NumberSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("media").ToLocalChecked(), MediaGetter, MediaSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("displayName").ToLocalChecked(), DisplayNameGetter, DisplayNameSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("contactPhone").ToLocalChecked(), ContactPhoneGetter, ContactPhoneSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("contact").ToLocalChecked(), ContactGetter, ContactSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("audioEndpoint").ToLocalChecked(), AudioEndpointGetter, AudioEndpointSetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneDialOptions").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneDialOptions(::Windows::ApplicationModel::Calls::PhoneDialOptions^ 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::ApplicationModel::Calls::PhoneDialOptions^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneDialOptions^) NodeRT::Utils::GetObjectInstance(info[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
      else if (info.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::ApplicationModel::Calls::PhoneDialOptions();
        }
        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());

      PhoneDialOptions *wrapperInstance = new PhoneDialOptions(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::ApplicationModel::Calls::PhoneDialOptions^>(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::ApplicationModel::Calls::PhoneDialOptions^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneDialOptions^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneDialOptions(winRtInstance));
    }


  



    static void NumberGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->Number;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void NumberSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->Number = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void MediaGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallMedia result = wrapper->_instance->Media;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void MediaSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallMedia winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneCallMedia>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->Media = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void DisplayNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(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 DisplayNameSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->DisplayName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void ContactPhoneGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Contacts::ContactPhone^ result = wrapper->_instance->ContactPhone;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.ApplicationModel.Contacts", "ContactPhone", result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void ContactPhoneSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Contacts::ContactPhone^>(value))
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Contacts::ContactPhone^ winRtValue = dynamic_cast<::Windows::ApplicationModel::Contacts::ContactPhone^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->ContactPhone = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void ContactGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Contacts::Contact^ result = wrapper->_instance->Contact;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.ApplicationModel.Contacts", "Contact", result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void ContactSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Contacts::Contact^>(value))
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Contacts::Contact^ winRtValue = dynamic_cast<::Windows::ApplicationModel::Contacts::Contact^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->Contact = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void AudioEndpointGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneAudioRoutingEndpoint result = wrapper->_instance->AudioEndpoint;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void AudioEndpointSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneDialOptions^>(info.This()))
      {
        return;
      }

      PhoneDialOptions *wrapper = PhoneDialOptions::Unwrap<PhoneDialOptions>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneAudioRoutingEndpoint winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneAudioRoutingEndpoint>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->AudioEndpoint = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneDialOptions^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneDialOptions(::Windows::ApplicationModel::Calls::PhoneDialOptions^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneDialOptions^ UnwrapPhoneDialOptions(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneDialOptions::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneDialOptions(::Windows::ApplicationModel::Calls::PhoneDialOptions^ 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>(PhoneDialOptions::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneDialOptions^ UnwrapPhoneDialOptions(Local<Value> value)
  {
     return PhoneDialOptions::Unwrap<PhoneDialOptions>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneDialOptions(Local<Object> exports)
  {
    PhoneDialOptions::Init(exports);
  }

  class PhoneLineWatcher : 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>("PhoneLineWatcher").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      Nan::SetPrototypeMethod(localRef, "start", Start);
      Nan::SetPrototypeMethod(localRef, "stop", Stop);
      
                  
      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>("status").ToLocalChecked(), StatusGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneLineWatcher").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneLineWatcher(::Windows::ApplicationModel::Calls::PhoneLineWatcher^ 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::ApplicationModel::Calls::PhoneLineWatcher^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineWatcher^) 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());

      PhoneLineWatcher *wrapperInstance = new PhoneLineWatcher(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::ApplicationModel::Calls::PhoneLineWatcher^>(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::ApplicationModel::Calls::PhoneLineWatcher^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineWatcher^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneLineWatcher(winRtInstance));
    }


  
    static void Start(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(info.This()))
      {
        return;
      }

      PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->Start();
          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 Stop(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(info.This()))
      {
        return;
      }

      PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->Stop();
          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 StatusGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(info.This()))
      {
        return;
      }

      PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneLineWatcherStatus result = wrapper->_instance->Status;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(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(info[0]);
      auto str = *eventName;
      
      Local<Function> callback = info[1].As<Function>();
      
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"enumerationCompleted", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
        }
        PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(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->EnumerationCompleted::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::PhoneLineWatcher^, ::Platform::Object^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::PhoneLineWatcher^ arg0, ::Platform::Object^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapPhoneLineWatcher(arg0);
                Local<Value> wrappedArg1 = CreateOpaqueWrapper(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"lineAdded", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
        }
        PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(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->LineAdded::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::PhoneLineWatcher^, ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::PhoneLineWatcher^ arg0, ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapPhoneLineWatcher(arg0);
                Local<Value> wrappedArg1 = WrapPhoneLineWatcherEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"lineRemoved", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
        }
        PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(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->LineRemoved::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::PhoneLineWatcher^, ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::PhoneLineWatcher^ arg0, ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapPhoneLineWatcher(arg0);
                Local<Value> wrappedArg1 = WrapPhoneLineWatcherEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"lineUpdated", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
        }
        PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(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->LineUpdated::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::PhoneLineWatcher^, ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::PhoneLineWatcher^ arg0, ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapPhoneLineWatcher(arg0);
                Local<Value> wrappedArg1 = WrapPhoneLineWatcherEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"stopped", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
        }
        PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(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->Stopped::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::PhoneLineWatcher^, ::Platform::Object^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::PhoneLineWatcher^ arg0, ::Platform::Object^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapPhoneLineWatcher(arg0);
                Local<Value> wrappedArg1 = CreateOpaqueWrapper(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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(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(info[0]);
      auto str = *eventName;

      if ((NodeRT::Utils::CaseInsenstiveEquals(L"enumerationCompleted", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"lineAdded", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"lineRemoved", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"lineUpdated", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"stopped", str)))
      {
        Nan::ThrowError(Nan::Error(String::Concat(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"enumerationCompleted", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
          }
          PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());
          wrapper->_instance->EnumerationCompleted::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"lineAdded", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
          }
          PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());
          wrapper->_instance->LineAdded::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"lineRemoved", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
          }
          PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());
          wrapper->_instance->LineRemoved::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"lineUpdated", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
          }
          PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());
          wrapper->_instance->LineUpdated::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"stopped", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcher^>(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;
          }
          PhoneLineWatcher *wrapper = PhoneLineWatcher::Unwrap<PhoneLineWatcher>(info.This());
          wrapper->_instance->Stopped::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::ApplicationModel::Calls::PhoneLineWatcher^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneLineWatcher(::Windows::ApplicationModel::Calls::PhoneLineWatcher^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneLineWatcher^ UnwrapPhoneLineWatcher(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneLineWatcher::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneLineWatcher(::Windows::ApplicationModel::Calls::PhoneLineWatcher^ 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>(PhoneLineWatcher::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneLineWatcher^ UnwrapPhoneLineWatcher(Local<Value> value)
  {
     return PhoneLineWatcher::Unwrap<PhoneLineWatcher>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneLineWatcher(Local<Object> exports)
  {
    PhoneLineWatcher::Init(exports);
  }

  class PhoneLineWatcherEventArgs : 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>("PhoneLineWatcherEventArgs").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("lineId").ToLocalChecked(), LineIdGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneLineWatcherEventArgs").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneLineWatcherEventArgs(::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ 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::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^) 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());

      PhoneLineWatcherEventArgs *wrapperInstance = new PhoneLineWatcherEventArgs(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::ApplicationModel::Calls::PhoneLineWatcherEventArgs^>(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::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneLineWatcherEventArgs(winRtInstance));
    }


  



    static void LineIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^>(info.This()))
      {
        return;
      }

      PhoneLineWatcherEventArgs *wrapper = PhoneLineWatcherEventArgs::Unwrap<PhoneLineWatcherEventArgs>(info.This());

      try 
      {
        ::Platform::Guid result = wrapper->_instance->LineId;
        info.GetReturnValue().Set(NodeRT::Utils::GuidToJs(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneLineWatcherEventArgs(::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ UnwrapPhoneLineWatcherEventArgs(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneLineWatcherEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneLineWatcherEventArgs(::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ 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>(PhoneLineWatcherEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneLineWatcherEventArgs^ UnwrapPhoneLineWatcherEventArgs(Local<Value> value)
  {
     return PhoneLineWatcherEventArgs::Unwrap<PhoneLineWatcherEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneLineWatcherEventArgs(Local<Object> exports)
  {
    PhoneLineWatcherEventArgs::Init(exports);
  }

  class PhoneCallStore : 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>("PhoneCallStore").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
            
      Nan::SetPrototypeMethod(localRef, "requestLineWatcher", RequestLineWatcher);
      
            
      Nan::SetPrototypeMethod(localRef, "isEmergencyPhoneNumberAsync", IsEmergencyPhoneNumberAsync);
      Nan::SetPrototypeMethod(localRef, "getDefaultLineAsync", GetDefaultLineAsync);
      
                  
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallStore").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallStore(::Windows::ApplicationModel::Calls::PhoneCallStore^ 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::ApplicationModel::Calls::PhoneCallStore^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallStore^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallStore^) 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());

      PhoneCallStore *wrapperInstance = new PhoneCallStore(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::ApplicationModel::Calls::PhoneCallStore^>(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::ApplicationModel::Calls::PhoneCallStore^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallStore^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallStore(winRtInstance));
    }


    static void IsEmergencyPhoneNumberAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallStore *wrapper = PhoneCallStore::Unwrap<PhoneCallStore>(info.This());

      ::Windows::Foundation::IAsyncOperation<bool>^ op;
    

      if (info.Length() == 2
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          
          op = wrapper->_instance->IsEmergencyPhoneNumberAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<bool> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = Nan::New<Boolean>(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void GetDefaultLineAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallStore *wrapper = PhoneCallStore::Unwrap<PhoneCallStore>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Platform::Guid>^ op;
    

      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->GetDefaultLineAsync();
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Platform::Guid> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = NodeRT::Utils::GuidToJs(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
  
    static void RequestLineWatcher(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallStore^>(info.This()))
      {
        return;
      }

      PhoneCallStore *wrapper = PhoneCallStore::Unwrap<PhoneCallStore>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneLineWatcher^ result;
          result = wrapper->_instance->RequestLineWatcher();
          info.GetReturnValue().Set(WrapPhoneLineWatcher(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::ApplicationModel::Calls::PhoneCallStore^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallStore(::Windows::ApplicationModel::Calls::PhoneCallStore^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallStore^ UnwrapPhoneCallStore(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallStore::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallStore(::Windows::ApplicationModel::Calls::PhoneCallStore^ 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>(PhoneCallStore::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallStore^ UnwrapPhoneCallStore(Local<Value> value)
  {
     return PhoneCallStore::Unwrap<PhoneCallStore>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallStore(Local<Object> exports)
  {
    PhoneCallStore::Init(exports);
  }

  class PhoneCallManager : 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>("PhoneCallManager").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
                              
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);

      Nan::SetMethod(constructor, "showPhoneCallSettingsUI", ShowPhoneCallSettingsUI);
      Nan::SetMethod(constructor, "showPhoneCallUI", ShowPhoneCallUI);
      func = Nan::GetFunction(Nan::New<FunctionTemplate>(RequestStoreAsync)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("requestStoreAsync").ToLocalChecked(), func);
      Nan::SetAccessor(constructor, Nan::New<String>("isCallActive").ToLocalChecked(), IsCallActiveGetter);
      Nan::SetAccessor(constructor, Nan::New<String>("isCallIncoming").ToLocalChecked(), IsCallIncomingGetter);
      
      Local<Function> addListenerFunc = Nan::GetFunction(Nan::New<FunctionTemplate>(AddListener)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("addListener").ToLocalChecked(), addListenerFunc);
      Nan::Set(constructor, Nan::New<String>("on").ToLocalChecked(), addListenerFunc);
      Local<Function> removeListenerFunc = Nan::GetFunction(Nan::New<FunctionTemplate>(RemoveListener)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("removeListener").ToLocalChecked(), removeListenerFunc);
      Nan::Set(constructor, Nan::New<String>("off").ToLocalChecked(), removeListenerFunc);

      Nan::Set(exports, Nan::New<String>("PhoneCallManager").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallManager(::Windows::ApplicationModel::Calls::PhoneCallManager^ 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::ApplicationModel::Calls::PhoneCallManager^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallManager^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallManager^) 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());

      PhoneCallManager *wrapperInstance = new PhoneCallManager(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::ApplicationModel::Calls::PhoneCallManager^>(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::ApplicationModel::Calls::PhoneCallManager^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallManager^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallManager(winRtInstance));
    }


  

    static void RequestStoreAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::ApplicationModel::Calls::PhoneCallStore^>^ op;
      

      if (info.Length() == 1)
      {
        try
        {
          op = ::Windows::ApplicationModel::Calls::PhoneCallManager::RequestStoreAsync();
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::ApplicationModel::Calls::PhoneCallStore^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = WrapPhoneCallStore(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

	  	    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }

    static void ShowPhoneCallSettingsUI(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallManager::ShowPhoneCallSettingsUI();
          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 ShowPhoneCallUI(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 2
        && info[0]->IsString()
        && info[1]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[1])));
          
          ::Windows::ApplicationModel::Calls::PhoneCallManager::ShowPhoneCallUI(arg0, arg1);
          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 IsCallActiveGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;

      try 
      {
        bool result = ::Windows::ApplicationModel::Calls::PhoneCallManager::IsCallActive;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsCallIncomingGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;

      try 
      {
        bool result = ::Windows::ApplicationModel::Calls::PhoneCallManager::IsCallIncoming;
        info.GetReturnValue().Set(Nan::New<Boolean>(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(info[0]);
      auto str = *eventName;
      
      Local<Function> callback = info[1].As<Function>();
      
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"callStateChanged", 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::ApplicationModel::Calls::PhoneCallManager::CallStateChanged::add(
            ref new ::Windows::Foundation::EventHandler<::Platform::Object^>(
            [callbackObjPtr](::Platform::Object^ arg0, ::Platform::Object^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = CreateOpaqueWrapper(arg0);
                Local<Value> wrappedArg1 = CreateOpaqueWrapper(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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(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(info[0]);
      auto str = *eventName;

      if ((NodeRT::Utils::CaseInsenstiveEquals(L"callStateChanged", str)))
      {
        Nan::ThrowError(Nan::Error(String::Concat(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"callStateChanged", str))
        {
          ::Windows::ApplicationModel::Calls::PhoneCallManager::CallStateChanged::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::ApplicationModel::Calls::PhoneCallManager^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallManager(::Windows::ApplicationModel::Calls::PhoneCallManager^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallManager^ UnwrapPhoneCallManager(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallManager::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallManager(::Windows::ApplicationModel::Calls::PhoneCallManager^ 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>(PhoneCallManager::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallManager^ UnwrapPhoneCallManager(Local<Value> value)
  {
     return PhoneCallManager::Unwrap<PhoneCallManager>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallManager(Local<Object> exports)
  {
    PhoneCallManager::Init(exports);
  }

  class PhoneCallVideoCapabilitiesManager : 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>("PhoneCallVideoCapabilitiesManager").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
                              
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);

      func = Nan::GetFunction(Nan::New<FunctionTemplate>(GetCapabilitiesAsync)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("getCapabilitiesAsync").ToLocalChecked(), func);

      Nan::Set(exports, Nan::New<String>("PhoneCallVideoCapabilitiesManager").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallVideoCapabilitiesManager(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ 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::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^) 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());

      PhoneCallVideoCapabilitiesManager *wrapperInstance = new PhoneCallVideoCapabilitiesManager(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::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^>(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::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallVideoCapabilitiesManager(winRtInstance));
    }


  

    static void GetCapabilitiesAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^>^ op;
      

      if (info.Length() == 2
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          
          op = ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager::GetCapabilitiesAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilities^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = WrapPhoneCallVideoCapabilities(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

	  	    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }




  private:
    ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallVideoCapabilitiesManager(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ UnwrapPhoneCallVideoCapabilitiesManager(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallVideoCapabilitiesManager::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallVideoCapabilitiesManager(::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ 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>(PhoneCallVideoCapabilitiesManager::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallVideoCapabilitiesManager^ UnwrapPhoneCallVideoCapabilitiesManager(Local<Value> value)
  {
     return PhoneCallVideoCapabilitiesManager::Unwrap<PhoneCallVideoCapabilitiesManager>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallVideoCapabilitiesManager(Local<Object> exports)
  {
    PhoneCallVideoCapabilitiesManager::Init(exports);
  }

  class PhoneCallBlocking : 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>("PhoneCallBlocking").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
                              
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);

      func = Nan::GetFunction(Nan::New<FunctionTemplate>(SetCallBlockingListAsync)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("setCallBlockingListAsync").ToLocalChecked(), func);
      Nan::SetAccessor(constructor, Nan::New<String>("blockUnknownNumbers").ToLocalChecked(), BlockUnknownNumbersGetter, BlockUnknownNumbersSetter);
      Nan::SetAccessor(constructor, Nan::New<String>("blockPrivateNumbers").ToLocalChecked(), BlockPrivateNumbersGetter, BlockPrivateNumbersSetter);

      Nan::Set(exports, Nan::New<String>("PhoneCallBlocking").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallBlocking(::Windows::ApplicationModel::Calls::PhoneCallBlocking^ 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::ApplicationModel::Calls::PhoneCallBlocking^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallBlocking^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallBlocking^) 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());

      PhoneCallBlocking *wrapperInstance = new PhoneCallBlocking(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::ApplicationModel::Calls::PhoneCallBlocking^>(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::ApplicationModel::Calls::PhoneCallBlocking^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallBlocking^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallBlocking(winRtInstance));
    }


  

    static void SetCallBlockingListAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      ::Windows::Foundation::IAsyncOperation<bool>^ op;
      

      if (info.Length() == 2
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Platform::String^>^>(info[0]) || info[0]->IsArray()))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Platform::String^>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Platform::String^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Platform::String^>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return (!NodeRT::Utils::IsWinRtWrapper(value));
                 },
                 [](Local<Value> value) -> ::Platform::String^ {
                   return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Platform::String^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          
          op = ::Windows::ApplicationModel::Calls::PhoneCallBlocking::SetCallBlockingListAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<bool> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = Nan::New<Boolean>(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

	  	    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }



    static void BlockUnknownNumbersGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;

      try 
      {
        bool result = ::Windows::ApplicationModel::Calls::PhoneCallBlocking::BlockUnknownNumbers;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void BlockUnknownNumbersSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      try 
      {

        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        ::Windows::ApplicationModel::Calls::PhoneCallBlocking::BlockUnknownNumbers = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void BlockPrivateNumbersGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;

      try 
      {
        bool result = ::Windows::ApplicationModel::Calls::PhoneCallBlocking::BlockPrivateNumbers;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void BlockPrivateNumbersSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      try 
      {

        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        ::Windows::ApplicationModel::Calls::PhoneCallBlocking::BlockPrivateNumbers = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    

  private:
    ::Windows::ApplicationModel::Calls::PhoneCallBlocking^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallBlocking(::Windows::ApplicationModel::Calls::PhoneCallBlocking^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallBlocking^ UnwrapPhoneCallBlocking(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallBlocking::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallBlocking(::Windows::ApplicationModel::Calls::PhoneCallBlocking^ 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>(PhoneCallBlocking::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallBlocking^ UnwrapPhoneCallBlocking(Local<Value> value)
  {
     return PhoneCallBlocking::Unwrap<PhoneCallBlocking>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallBlocking(Local<Object> exports)
  {
    PhoneCallBlocking::Init(exports);
  }

  class CallStateChangeEventArgs : 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>("CallStateChangeEventArgs").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("state").ToLocalChecked(), StateGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("CallStateChangeEventArgs").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CallStateChangeEventArgs(::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ 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::ApplicationModel::Calls::CallStateChangeEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^) 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());

      CallStateChangeEventArgs *wrapperInstance = new CallStateChangeEventArgs(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::ApplicationModel::Calls::CallStateChangeEventArgs^>(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::ApplicationModel::Calls::CallStateChangeEventArgs^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapCallStateChangeEventArgs(winRtInstance));
    }


  



    static void StateGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^>(info.This()))
      {
        return;
      }

      CallStateChangeEventArgs *wrapper = CallStateChangeEventArgs::Unwrap<CallStateChangeEventArgs>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::VoipPhoneCallState result = wrapper->_instance->State;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapCallStateChangeEventArgs(::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ UnwrapCallStateChangeEventArgs(Local<Value> value);
  };
  Persistent<FunctionTemplate> CallStateChangeEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapCallStateChangeEventArgs(::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ 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>(CallStateChangeEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ UnwrapCallStateChangeEventArgs(Local<Value> value)
  {
     return CallStateChangeEventArgs::Unwrap<CallStateChangeEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitCallStateChangeEventArgs(Local<Object> exports)
  {
    CallStateChangeEventArgs::Init(exports);
  }

  class CallAnswerEventArgs : 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>("CallAnswerEventArgs").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("acceptedMedia").ToLocalChecked(), AcceptedMediaGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("CallAnswerEventArgs").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CallAnswerEventArgs(::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ 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::ApplicationModel::Calls::CallAnswerEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::CallAnswerEventArgs^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::CallAnswerEventArgs^) 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());

      CallAnswerEventArgs *wrapperInstance = new CallAnswerEventArgs(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::ApplicationModel::Calls::CallAnswerEventArgs^>(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::ApplicationModel::Calls::CallAnswerEventArgs^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::CallAnswerEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapCallAnswerEventArgs(winRtInstance));
    }


  



    static void AcceptedMediaGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::CallAnswerEventArgs^>(info.This()))
      {
        return;
      }

      CallAnswerEventArgs *wrapper = CallAnswerEventArgs::Unwrap<CallAnswerEventArgs>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::VoipPhoneCallMedia result = wrapper->_instance->AcceptedMedia;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapCallAnswerEventArgs(::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ UnwrapCallAnswerEventArgs(Local<Value> value);
  };
  Persistent<FunctionTemplate> CallAnswerEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapCallAnswerEventArgs(::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ 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>(CallAnswerEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ UnwrapCallAnswerEventArgs(Local<Value> value)
  {
     return CallAnswerEventArgs::Unwrap<CallAnswerEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitCallAnswerEventArgs(Local<Object> exports)
  {
    CallAnswerEventArgs::Init(exports);
  }

  class CallRejectEventArgs : 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>("CallRejectEventArgs").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("rejectReason").ToLocalChecked(), RejectReasonGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("CallRejectEventArgs").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CallRejectEventArgs(::Windows::ApplicationModel::Calls::CallRejectEventArgs^ 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::ApplicationModel::Calls::CallRejectEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::CallRejectEventArgs^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::CallRejectEventArgs^) 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());

      CallRejectEventArgs *wrapperInstance = new CallRejectEventArgs(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::ApplicationModel::Calls::CallRejectEventArgs^>(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::ApplicationModel::Calls::CallRejectEventArgs^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::CallRejectEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapCallRejectEventArgs(winRtInstance));
    }


  



    static void RejectReasonGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::CallRejectEventArgs^>(info.This()))
      {
        return;
      }

      CallRejectEventArgs *wrapper = CallRejectEventArgs::Unwrap<CallRejectEventArgs>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::VoipPhoneCallRejectReason result = wrapper->_instance->RejectReason;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::CallRejectEventArgs^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapCallRejectEventArgs(::Windows::ApplicationModel::Calls::CallRejectEventArgs^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::CallRejectEventArgs^ UnwrapCallRejectEventArgs(Local<Value> value);
  };
  Persistent<FunctionTemplate> CallRejectEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapCallRejectEventArgs(::Windows::ApplicationModel::Calls::CallRejectEventArgs^ 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>(CallRejectEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::CallRejectEventArgs^ UnwrapCallRejectEventArgs(Local<Value> value)
  {
     return CallRejectEventArgs::Unwrap<CallRejectEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitCallRejectEventArgs(Local<Object> exports)
  {
    CallRejectEventArgs::Init(exports);
  }

  class VoipPhoneCall : 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>("VoipPhoneCall").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      Nan::SetPrototypeMethod(localRef, "notifyCallHeld", NotifyCallHeld);
      Nan::SetPrototypeMethod(localRef, "notifyCallActive", NotifyCallActive);
      Nan::SetPrototypeMethod(localRef, "notifyCallEnded", NotifyCallEnded);
      Nan::SetPrototypeMethod(localRef, "notifyCallReady", NotifyCallReady);
      
                  
      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>("startTime").ToLocalChecked(), StartTimeGetter, StartTimeSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("contactName").ToLocalChecked(), ContactNameGetter, ContactNameSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("callMedia").ToLocalChecked(), CallMediaGetter, CallMediaSetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("VoipPhoneCall").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    VoipPhoneCall(::Windows::ApplicationModel::Calls::VoipPhoneCall^ 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::ApplicationModel::Calls::VoipPhoneCall^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::VoipPhoneCall^) 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());

      VoipPhoneCall *wrapperInstance = new VoipPhoneCall(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::ApplicationModel::Calls::VoipPhoneCall^>(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::ApplicationModel::Calls::VoipPhoneCall^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::VoipPhoneCall^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapVoipPhoneCall(winRtInstance));
    }


  
    static void NotifyCallHeld(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->NotifyCallHeld();
          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 NotifyCallActive(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->NotifyCallActive();
          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 NotifyCallEnded(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->NotifyCallEnded();
          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 NotifyCallReady(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->NotifyCallReady();
          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 StartTimeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->StartTime;
        info.GetReturnValue().Set(NodeRT::Utils::DateTimeToJS(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void StartTimeSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsDate())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      try 
      {
        
        ::Windows::Foundation::DateTime winRtValue = NodeRT::Utils::DateTimeFromJSDate(value);

        wrapper->_instance->StartTime = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void ContactNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->ContactName;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void ContactNameSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->ContactName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void CallMediaGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::VoipPhoneCallMedia result = wrapper->_instance->CallMedia;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void CallMediaSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(info.This()))
      {
        return;
      }

      VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::VoipPhoneCallMedia winRtValue = static_cast<::Windows::ApplicationModel::Calls::VoipPhoneCallMedia>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->CallMedia = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    


    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(info[0]);
      auto str = *eventName;
      
      Local<Function> callback = info[1].As<Function>();
      
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"answerRequested", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
        }
        VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(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->AnswerRequested::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::VoipPhoneCall^, ::Windows::ApplicationModel::Calls::CallAnswerEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::VoipPhoneCall^ arg0, ::Windows::ApplicationModel::Calls::CallAnswerEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapVoipPhoneCall(arg0);
                Local<Value> wrappedArg1 = WrapCallAnswerEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"endRequested", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
        }
        VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(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->EndRequested::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::VoipPhoneCall^, ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::VoipPhoneCall^ arg0, ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapVoipPhoneCall(arg0);
                Local<Value> wrappedArg1 = WrapCallStateChangeEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"holdRequested", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
        }
        VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(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->HoldRequested::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::VoipPhoneCall^, ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::VoipPhoneCall^ arg0, ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapVoipPhoneCall(arg0);
                Local<Value> wrappedArg1 = WrapCallStateChangeEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"rejectRequested", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
        }
        VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(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->RejectRequested::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::VoipPhoneCall^, ::Windows::ApplicationModel::Calls::CallRejectEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::VoipPhoneCall^ arg0, ::Windows::ApplicationModel::Calls::CallRejectEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapVoipPhoneCall(arg0);
                Local<Value> wrappedArg1 = WrapCallRejectEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"resumeRequested", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
        }
        VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(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->ResumeRequested::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::VoipPhoneCall^, ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::VoipPhoneCall^ arg0, ::Windows::ApplicationModel::Calls::CallStateChangeEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapVoipPhoneCall(arg0);
                Local<Value> wrappedArg1 = WrapCallStateChangeEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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(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(info[0]);
      auto str = *eventName;

      if ((NodeRT::Utils::CaseInsenstiveEquals(L"answerRequested", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"endRequested", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"holdRequested", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"rejectRequested", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"resumeRequested", str)))
      {
        Nan::ThrowError(Nan::Error(String::Concat(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"answerRequested", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
          }
          VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());
          wrapper->_instance->AnswerRequested::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"endRequested", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
          }
          VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());
          wrapper->_instance->EndRequested::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"holdRequested", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
          }
          VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());
          wrapper->_instance->HoldRequested::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"rejectRequested", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
          }
          VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());
          wrapper->_instance->RejectRequested::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"resumeRequested", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipPhoneCall^>(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;
          }
          VoipPhoneCall *wrapper = VoipPhoneCall::Unwrap<VoipPhoneCall>(info.This());
          wrapper->_instance->ResumeRequested::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::ApplicationModel::Calls::VoipPhoneCall^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapVoipPhoneCall(::Windows::ApplicationModel::Calls::VoipPhoneCall^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::VoipPhoneCall^ UnwrapVoipPhoneCall(Local<Value> value);
  };
  Persistent<FunctionTemplate> VoipPhoneCall::s_constructorTemplate;

  v8::Local<v8::Value> WrapVoipPhoneCall(::Windows::ApplicationModel::Calls::VoipPhoneCall^ 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>(VoipPhoneCall::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::VoipPhoneCall^ UnwrapVoipPhoneCall(Local<Value> value)
  {
     return VoipPhoneCall::Unwrap<VoipPhoneCall>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitVoipPhoneCall(Local<Object> exports)
  {
    VoipPhoneCall::Init(exports);
  }

  class MuteChangeEventArgs : 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>("MuteChangeEventArgs").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("muted").ToLocalChecked(), MutedGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("MuteChangeEventArgs").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    MuteChangeEventArgs(::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ 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::ApplicationModel::Calls::MuteChangeEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::MuteChangeEventArgs^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::MuteChangeEventArgs^) 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());

      MuteChangeEventArgs *wrapperInstance = new MuteChangeEventArgs(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::ApplicationModel::Calls::MuteChangeEventArgs^>(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::ApplicationModel::Calls::MuteChangeEventArgs^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::MuteChangeEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapMuteChangeEventArgs(winRtInstance));
    }


  



    static void MutedGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::MuteChangeEventArgs^>(info.This()))
      {
        return;
      }

      MuteChangeEventArgs *wrapper = MuteChangeEventArgs::Unwrap<MuteChangeEventArgs>(info.This());

      try 
      {
        bool result = wrapper->_instance->Muted;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapMuteChangeEventArgs(::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ UnwrapMuteChangeEventArgs(Local<Value> value);
  };
  Persistent<FunctionTemplate> MuteChangeEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapMuteChangeEventArgs(::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ 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>(MuteChangeEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ UnwrapMuteChangeEventArgs(Local<Value> value)
  {
     return MuteChangeEventArgs::Unwrap<MuteChangeEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMuteChangeEventArgs(Local<Object> exports)
  {
    MuteChangeEventArgs::Init(exports);
  }

  class VoipCallCoordinator : 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>("VoipCallCoordinator").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
            
      Nan::SetPrototypeMethod(localRef, "requestNewIncomingCall", RequestNewIncomingCall);
      Nan::SetPrototypeMethod(localRef, "requestNewOutgoingCall", RequestNewOutgoingCall);
      Nan::SetPrototypeMethod(localRef, "notifyMuted", NotifyMuted);
      Nan::SetPrototypeMethod(localRef, "notifyUnmuted", NotifyUnmuted);
      Nan::SetPrototypeMethod(localRef, "requestOutgoingUpgradeToVideoCall", RequestOutgoingUpgradeToVideoCall);
      Nan::SetPrototypeMethod(localRef, "requestIncomingUpgradeToVideoCall", RequestIncomingUpgradeToVideoCall);
      Nan::SetPrototypeMethod(localRef, "terminateCellularCall", TerminateCellularCall);
      Nan::SetPrototypeMethod(localRef, "cancelUpgrade", CancelUpgrade);
      
            
      Nan::SetPrototypeMethod(localRef, "reserveCallResourcesAsync", ReserveCallResourcesAsync);
      
            
      Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
      Nan::SetPrototypeMethod(localRef,"on", AddListener);
      Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
      Nan::SetPrototypeMethod(localRef, "off", RemoveListener);
            
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);

      Nan::SetMethod(constructor, "getDefault", GetDefault);

      Nan::Set(exports, Nan::New<String>("VoipCallCoordinator").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    VoipCallCoordinator(::Windows::ApplicationModel::Calls::VoipCallCoordinator^ 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::ApplicationModel::Calls::VoipCallCoordinator^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::VoipCallCoordinator^) 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());

      VoipCallCoordinator *wrapperInstance = new VoipCallCoordinator(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::ApplicationModel::Calls::VoipCallCoordinator^>(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::ApplicationModel::Calls::VoipCallCoordinator^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::VoipCallCoordinator^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapVoipCallCoordinator(winRtInstance));
    }


    static void ReserveCallResourcesAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::ApplicationModel::Calls::VoipPhoneCallResourceReservationStatus>^ op;
    

      if (info.Length() == 2
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          
          op = wrapper->_instance->ReserveCallResourcesAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::ApplicationModel::Calls::VoipPhoneCallResourceReservationStatus> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = Nan::New<Integer>(static_cast<int>(result));
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
  
    static void RequestNewIncomingCall(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 10
        && info[0]->IsString()
        && info[1]->IsString()
        && info[2]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Uri^>(info[3])
        && info[4]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Uri^>(info[5])
        && info[6]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Uri^>(info[7])
        && info[8]->IsInt32()
        && info[9]->IsNumber())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[1])));
          Platform::String^ arg2 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[2])));
          ::Windows::Foundation::Uri^ arg3 = dynamic_cast<::Windows::Foundation::Uri^>(NodeRT::Utils::GetObjectInstance(info[3]));
          Platform::String^ arg4 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[4])));
          ::Windows::Foundation::Uri^ arg5 = dynamic_cast<::Windows::Foundation::Uri^>(NodeRT::Utils::GetObjectInstance(info[5]));
          Platform::String^ arg6 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[6])));
          ::Windows::Foundation::Uri^ arg7 = dynamic_cast<::Windows::Foundation::Uri^>(NodeRT::Utils::GetObjectInstance(info[7]));
          ::Windows::ApplicationModel::Calls::VoipPhoneCallMedia arg8 = static_cast<::Windows::ApplicationModel::Calls::VoipPhoneCallMedia>(Nan::To<int32_t>(info[8]).FromMaybe(0));
          ::Windows::Foundation::TimeSpan arg9 = NodeRT::Utils::TimeSpanFromMilli(Nan::To<int64_t>(info[9]).FromMaybe(0));
          
          ::Windows::ApplicationModel::Calls::VoipPhoneCall^ result;
          result = wrapper->_instance->RequestNewIncomingCall(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
          info.GetReturnValue().Set(WrapVoipPhoneCall(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 RequestNewOutgoingCall(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 4
        && info[0]->IsString()
        && info[1]->IsString()
        && info[2]->IsString()
        && info[3]->IsInt32())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[1])));
          Platform::String^ arg2 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[2])));
          ::Windows::ApplicationModel::Calls::VoipPhoneCallMedia arg3 = static_cast<::Windows::ApplicationModel::Calls::VoipPhoneCallMedia>(Nan::To<int32_t>(info[3]).FromMaybe(0));
          
          ::Windows::ApplicationModel::Calls::VoipPhoneCall^ result;
          result = wrapper->_instance->RequestNewOutgoingCall(arg0, arg1, arg2, arg3);
          info.GetReturnValue().Set(WrapVoipPhoneCall(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 NotifyMuted(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->NotifyMuted();
          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 NotifyUnmuted(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->NotifyUnmuted();
          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 RequestOutgoingUpgradeToVideoCall(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 4
        && NodeRT::Utils::IsGuid(info[0])
        && info[1]->IsString()
        && info[2]->IsString()
        && info[3]->IsString())
      {
        try
        {
          ::Platform::Guid arg0 = NodeRT::Utils::GuidFromJs(info[0]);
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[1])));
          Platform::String^ arg2 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[2])));
          Platform::String^ arg3 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[3])));
          
          ::Windows::ApplicationModel::Calls::VoipPhoneCall^ result;
          result = wrapper->_instance->RequestOutgoingUpgradeToVideoCall(arg0, arg1, arg2, arg3);
          info.GetReturnValue().Set(WrapVoipPhoneCall(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 RequestIncomingUpgradeToVideoCall(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 9
        && info[0]->IsString()
        && info[1]->IsString()
        && info[2]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Uri^>(info[3])
        && info[4]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Uri^>(info[5])
        && info[6]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Uri^>(info[7])
        && info[8]->IsNumber())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[1])));
          Platform::String^ arg2 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[2])));
          ::Windows::Foundation::Uri^ arg3 = dynamic_cast<::Windows::Foundation::Uri^>(NodeRT::Utils::GetObjectInstance(info[3]));
          Platform::String^ arg4 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[4])));
          ::Windows::Foundation::Uri^ arg5 = dynamic_cast<::Windows::Foundation::Uri^>(NodeRT::Utils::GetObjectInstance(info[5]));
          Platform::String^ arg6 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[6])));
          ::Windows::Foundation::Uri^ arg7 = dynamic_cast<::Windows::Foundation::Uri^>(NodeRT::Utils::GetObjectInstance(info[7]));
          ::Windows::Foundation::TimeSpan arg8 = NodeRT::Utils::TimeSpanFromMilli(Nan::To<int64_t>(info[8]).FromMaybe(0));
          
          ::Windows::ApplicationModel::Calls::VoipPhoneCall^ result;
          result = wrapper->_instance->RequestIncomingUpgradeToVideoCall(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
          info.GetReturnValue().Set(WrapVoipPhoneCall(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 TerminateCellularCall(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 1
        && NodeRT::Utils::IsGuid(info[0]))
      {
        try
        {
          ::Platform::Guid arg0 = NodeRT::Utils::GuidFromJs(info[0]);
          
          wrapper->_instance->TerminateCellularCall(arg0);
          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 CancelUpgrade(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(info.This()))
      {
        return;
      }

      VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());

      if (info.Length() == 1
        && NodeRT::Utils::IsGuid(info[0]))
      {
        try
        {
          ::Platform::Guid arg0 = NodeRT::Utils::GuidFromJs(info[0]);
          
          wrapper->_instance->CancelUpgrade(arg0);
          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 GetDefault(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::ApplicationModel::Calls::VoipCallCoordinator^ result;
          result = ::Windows::ApplicationModel::Calls::VoipCallCoordinator::GetDefault();
          info.GetReturnValue().Set(WrapVoipCallCoordinator(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 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(info[0]);
      auto str = *eventName;
      
      Local<Function> callback = info[1].As<Function>();
      
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"muteStateChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(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;
        }
        VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(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->MuteStateChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::VoipCallCoordinator^, ::Windows::ApplicationModel::Calls::MuteChangeEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::VoipCallCoordinator^ arg0, ::Windows::ApplicationModel::Calls::MuteChangeEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapVoipCallCoordinator(arg0);
                Local<Value> wrappedArg1 = WrapMuteChangeEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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(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(info[0]);
      auto str = *eventName;

      if ((NodeRT::Utils::CaseInsenstiveEquals(L"muteStateChanged", str)))
      {
        Nan::ThrowError(Nan::Error(String::Concat(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"muteStateChanged", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::VoipCallCoordinator^>(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;
          }
          VoipCallCoordinator *wrapper = VoipCallCoordinator::Unwrap<VoipCallCoordinator>(info.This());
          wrapper->_instance->MuteStateChanged::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::ApplicationModel::Calls::VoipCallCoordinator^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapVoipCallCoordinator(::Windows::ApplicationModel::Calls::VoipCallCoordinator^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::VoipCallCoordinator^ UnwrapVoipCallCoordinator(Local<Value> value);
  };
  Persistent<FunctionTemplate> VoipCallCoordinator::s_constructorTemplate;

  v8::Local<v8::Value> WrapVoipCallCoordinator(::Windows::ApplicationModel::Calls::VoipCallCoordinator^ 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>(VoipCallCoordinator::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::VoipCallCoordinator^ UnwrapVoipCallCoordinator(Local<Value> value)
  {
     return VoipCallCoordinator::Unwrap<VoipCallCoordinator>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitVoipCallCoordinator(Local<Object> exports)
  {
    VoipCallCoordinator::Init(exports);
  }

  class LockScreenCallEndCallDeferral : 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>("LockScreenCallEndCallDeferral").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      Nan::SetPrototypeMethod(localRef, "complete", Complete);
      
                        
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("LockScreenCallEndCallDeferral").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    LockScreenCallEndCallDeferral(::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ 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::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^) 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());

      LockScreenCallEndCallDeferral *wrapperInstance = new LockScreenCallEndCallDeferral(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::ApplicationModel::Calls::LockScreenCallEndCallDeferral^>(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::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapLockScreenCallEndCallDeferral(winRtInstance));
    }


  
    static void Complete(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^>(info.This()))
      {
        return;
      }

      LockScreenCallEndCallDeferral *wrapper = LockScreenCallEndCallDeferral::Unwrap<LockScreenCallEndCallDeferral>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->Complete();
          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::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapLockScreenCallEndCallDeferral(::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ UnwrapLockScreenCallEndCallDeferral(Local<Value> value);
  };
  Persistent<FunctionTemplate> LockScreenCallEndCallDeferral::s_constructorTemplate;

  v8::Local<v8::Value> WrapLockScreenCallEndCallDeferral(::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ 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>(LockScreenCallEndCallDeferral::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ UnwrapLockScreenCallEndCallDeferral(Local<Value> value)
  {
     return LockScreenCallEndCallDeferral::Unwrap<LockScreenCallEndCallDeferral>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitLockScreenCallEndCallDeferral(Local<Object> exports)
  {
    LockScreenCallEndCallDeferral::Init(exports);
  }

  class LockScreenCallUI : 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>("LockScreenCallUI").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      Nan::SetPrototypeMethod(localRef, "dismiss", Dismiss);
      
                  
      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>("callTitle").ToLocalChecked(), CallTitleGetter, CallTitleSetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("LockScreenCallUI").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    LockScreenCallUI(::Windows::ApplicationModel::Calls::LockScreenCallUI^ 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::ApplicationModel::Calls::LockScreenCallUI^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::LockScreenCallUI^) 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());

      LockScreenCallUI *wrapperInstance = new LockScreenCallUI(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::ApplicationModel::Calls::LockScreenCallUI^>(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::ApplicationModel::Calls::LockScreenCallUI^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::LockScreenCallUI^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapLockScreenCallUI(winRtInstance));
    }


  
    static void Dismiss(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(info.This()))
      {
        return;
      }

      LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          wrapper->_instance->Dismiss();
          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 CallTitleGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(info.This()))
      {
        return;
      }

      LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->CallTitle;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void CallTitleSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(info.This()))
      {
        return;
      }

      LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->CallTitle = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    


    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(info[0]);
      auto str = *eventName;
      
      Local<Function> callback = info[1].As<Function>();
      
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"closed", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(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;
        }
        LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(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->Closed::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::LockScreenCallUI^, ::Platform::Object^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::LockScreenCallUI^ arg0, ::Platform::Object^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapLockScreenCallUI(arg0);
                Local<Value> wrappedArg1 = CreateOpaqueWrapper(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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"endRequested", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(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;
        }
        LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(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->EndRequested::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::ApplicationModel::Calls::LockScreenCallUI^, ::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^>(
            [callbackObjPtr](::Windows::ApplicationModel::Calls::LockScreenCallUI^ arg0, ::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
           	    HandleScope scope;
                TryCatch tryCatch;
              
                Local<Value> error;

                Local<Value> wrappedArg0 = WrapLockScreenCallUI(arg0);
                Local<Value> wrappedArg1 = WrapLockScreenCallEndRequestedEventArgs(arg1);

                if (tryCatch.HasCaught())
                {
                  error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
                }
                else 
                {
                  error = Undefined();
                }

				// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
				// can be fixed by wrapping the conversion code in a function and calling it on the fly
				// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
				tryCatch.~TryCatch();


                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(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(info[0]);
      auto str = *eventName;

      if ((NodeRT::Utils::CaseInsenstiveEquals(L"closed", str)) &&(NodeRT::Utils::CaseInsenstiveEquals(L"endRequested", str)))
      {
        Nan::ThrowError(Nan::Error(String::Concat(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"closed", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(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;
          }
          LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(info.This());
          wrapper->_instance->Closed::remove(registrationToken);
        }
        else if (NodeRT::Utils::CaseInsenstiveEquals(L"endRequested", str))
        {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallUI^>(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;
          }
          LockScreenCallUI *wrapper = LockScreenCallUI::Unwrap<LockScreenCallUI>(info.This());
          wrapper->_instance->EndRequested::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::ApplicationModel::Calls::LockScreenCallUI^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapLockScreenCallUI(::Windows::ApplicationModel::Calls::LockScreenCallUI^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::LockScreenCallUI^ UnwrapLockScreenCallUI(Local<Value> value);
  };
  Persistent<FunctionTemplate> LockScreenCallUI::s_constructorTemplate;

  v8::Local<v8::Value> WrapLockScreenCallUI(::Windows::ApplicationModel::Calls::LockScreenCallUI^ 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>(LockScreenCallUI::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::LockScreenCallUI^ UnwrapLockScreenCallUI(Local<Value> value)
  {
     return LockScreenCallUI::Unwrap<LockScreenCallUI>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitLockScreenCallUI(Local<Object> exports)
  {
    LockScreenCallUI::Init(exports);
  }

  class LockScreenCallEndRequestedEventArgs : 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>("LockScreenCallEndRequestedEventArgs").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      Nan::SetPrototypeMethod(localRef, "getDeferral", GetDeferral);
      
                        
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("deadline").ToLocalChecked(), DeadlineGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("LockScreenCallEndRequestedEventArgs").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    LockScreenCallEndRequestedEventArgs(::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ 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::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^) 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());

      LockScreenCallEndRequestedEventArgs *wrapperInstance = new LockScreenCallEndRequestedEventArgs(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::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^>(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::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapLockScreenCallEndRequestedEventArgs(winRtInstance));
    }


  
    static void GetDeferral(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^>(info.This()))
      {
        return;
      }

      LockScreenCallEndRequestedEventArgs *wrapper = LockScreenCallEndRequestedEventArgs::Unwrap<LockScreenCallEndRequestedEventArgs>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::ApplicationModel::Calls::LockScreenCallEndCallDeferral^ result;
          result = wrapper->_instance->GetDeferral();
          info.GetReturnValue().Set(WrapLockScreenCallEndCallDeferral(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 DeadlineGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^>(info.This()))
      {
        return;
      }

      LockScreenCallEndRequestedEventArgs *wrapper = LockScreenCallEndRequestedEventArgs::Unwrap<LockScreenCallEndRequestedEventArgs>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->Deadline;
        info.GetReturnValue().Set(NodeRT::Utils::DateTimeToJS(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapLockScreenCallEndRequestedEventArgs(::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ UnwrapLockScreenCallEndRequestedEventArgs(Local<Value> value);
  };
  Persistent<FunctionTemplate> LockScreenCallEndRequestedEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapLockScreenCallEndRequestedEventArgs(::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ 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>(LockScreenCallEndRequestedEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::LockScreenCallEndRequestedEventArgs^ UnwrapLockScreenCallEndRequestedEventArgs(Local<Value> value)
  {
     return LockScreenCallEndRequestedEventArgs::Unwrap<LockScreenCallEndRequestedEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitLockScreenCallEndRequestedEventArgs(Local<Object> exports)
  {
    LockScreenCallEndRequestedEventArgs::Init(exports);
  }

  class PhoneCallHistoryEntryAddress : 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>("PhoneCallHistoryEntryAddress").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("rawAddressKind").ToLocalChecked(), RawAddressKindGetter, RawAddressKindSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("rawAddress").ToLocalChecked(), RawAddressGetter, RawAddressSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("displayName").ToLocalChecked(), DisplayNameGetter, DisplayNameSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("contactId").ToLocalChecked(), ContactIdGetter, ContactIdSetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryAddress").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallHistoryEntryAddress(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ 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::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^) NodeRT::Utils::GetObjectInstance(info[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
      else if (info.Length() == 2
        && info[0]->IsString()
        && info[1]->IsInt32())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind arg1 = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind>(Nan::To<int32_t>(info[1]).FromMaybe(0));
          
          winRtInstance = ref new ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
      else if (info.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress();
        }
        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());

      PhoneCallHistoryEntryAddress *wrapperInstance = new PhoneCallHistoryEntryAddress(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::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(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::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallHistoryEntryAddress(winRtInstance));
    }


  



    static void RawAddressKindGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind result = wrapper->_instance->RawAddressKind;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void RawAddressKindSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryRawAddressKind>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->RawAddressKind = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void RawAddressGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->RawAddress;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void RawAddressSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->RawAddress = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void DisplayNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(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 DisplayNameSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->DisplayName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void ContactIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->ContactId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void ContactIdSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryAddress *wrapper = PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->ContactId = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallHistoryEntryAddress(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ UnwrapPhoneCallHistoryEntryAddress(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallHistoryEntryAddress::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallHistoryEntryAddress(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ 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>(PhoneCallHistoryEntryAddress::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ UnwrapPhoneCallHistoryEntryAddress(Local<Value> value)
  {
     return PhoneCallHistoryEntryAddress::Unwrap<PhoneCallHistoryEntryAddress>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallHistoryEntryAddress(Local<Object> exports)
  {
    PhoneCallHistoryEntryAddress::Init(exports);
  }

  class PhoneCallHistoryEntry : 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>("PhoneCallHistoryEntry").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("media").ToLocalChecked(), MediaGetter, MediaSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isMissed").ToLocalChecked(), IsMissedGetter, IsMissedSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isIncoming").ToLocalChecked(), IsIncomingGetter, IsIncomingSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isCallerIdBlocked").ToLocalChecked(), IsCallerIdBlockedGetter, IsCallerIdBlockedSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isSeen").ToLocalChecked(), IsSeenGetter, IsSeenSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("duration").ToLocalChecked(), DurationGetter, DurationSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isEmergency").ToLocalChecked(), IsEmergencyGetter, IsEmergencySetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isSuppressed").ToLocalChecked(), IsSuppressedGetter, IsSuppressedSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("startTime").ToLocalChecked(), StartTimeGetter, StartTimeSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceIdKind").ToLocalChecked(), SourceIdKindGetter, SourceIdKindSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("address").ToLocalChecked(), AddressGetter, AddressSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceId").ToLocalChecked(), SourceIdGetter, SourceIdSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("remoteId").ToLocalChecked(), RemoteIdGetter, RemoteIdSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("otherAppReadAccess").ToLocalChecked(), OtherAppReadAccessGetter, OtherAppReadAccessSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isRinging").ToLocalChecked(), IsRingingGetter, IsRingingSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isVoicemail").ToLocalChecked(), IsVoicemailGetter, IsVoicemailSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("id").ToLocalChecked(), IdGetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceDisplayName").ToLocalChecked(), SourceDisplayNameGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntry").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallHistoryEntry(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ 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::ApplicationModel::Calls::PhoneCallHistoryEntry^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^) NodeRT::Utils::GetObjectInstance(info[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
      else if (info.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry();
        }
        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());

      PhoneCallHistoryEntry *wrapperInstance = new PhoneCallHistoryEntry(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::ApplicationModel::Calls::PhoneCallHistoryEntry^>(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::ApplicationModel::Calls::PhoneCallHistoryEntry^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallHistoryEntry(winRtInstance));
    }


  



    static void MediaGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryMedia result = wrapper->_instance->Media;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void MediaSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryMedia winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryMedia>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->Media = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsMissedGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsMissed;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsMissedSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsMissed = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsIncomingGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsIncoming;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsIncomingSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsIncoming = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsCallerIdBlockedGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsCallerIdBlocked;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsCallerIdBlockedSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsCallerIdBlocked = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsSeenGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsSeen;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsSeenSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsSeen = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void DurationGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        ::Platform::IBox<::Windows::Foundation::TimeSpan>^ result = wrapper->_instance->Duration;
        info.GetReturnValue().Set(result ? static_cast<Local<Value>>(Nan::New<Number>(result->Value.Duration/10000.0)) : Undefined());
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void DurationSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsNumber())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        ::Platform::IBox<::Windows::Foundation::TimeSpan>^ winRtValue = ref new ::Platform::Box<::Windows::Foundation::TimeSpan>(NodeRT::Utils::TimeSpanFromMilli(Nan::To<int64_t>(value).FromMaybe(0)));

        wrapper->_instance->Duration = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsEmergencyGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsEmergency;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsEmergencySetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsEmergency = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsSuppressedGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsSuppressed;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsSuppressedSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsSuppressed = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void StartTimeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->StartTime;
        info.GetReturnValue().Set(NodeRT::Utils::DateTimeToJS(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void StartTimeSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsDate())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        ::Windows::Foundation::DateTime winRtValue = NodeRT::Utils::DateTimeFromJSDate(value);

        wrapper->_instance->StartTime = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void SourceIdKindGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallHistorySourceIdKind result = wrapper->_instance->SourceIdKind;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void SourceIdKindSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallHistorySourceIdKind winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistorySourceIdKind>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->SourceIdKind = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void AddressGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ result = wrapper->_instance->Address;
        info.GetReturnValue().Set(WrapPhoneCallHistoryEntryAddress(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void AddressSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(value))
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^ winRtValue = dynamic_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryAddress^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->Address = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void SourceIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->SourceId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void SourceIdSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->SourceId = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void RemoteIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->RemoteId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void RemoteIdSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->RemoteId = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void OtherAppReadAccessGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryOtherAppReadAccess result = wrapper->_instance->OtherAppReadAccess;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void OtherAppReadAccessSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryOtherAppReadAccess winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryOtherAppReadAccess>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->OtherAppReadAccess = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsRingingGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsRinging;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsRingingSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsRinging = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IsVoicemailGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsVoicemail;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void IsVoicemailSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        
        bool winRtValue = Nan::To<bool>(value).FromMaybe(false);

        wrapper->_instance->IsVoicemail = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void IdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->Id;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void SourceDisplayNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntry *wrapper = PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->SourceDisplayName;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallHistoryEntry(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ UnwrapPhoneCallHistoryEntry(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallHistoryEntry::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallHistoryEntry(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ 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>(PhoneCallHistoryEntry::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ UnwrapPhoneCallHistoryEntry(Local<Value> value)
  {
     return PhoneCallHistoryEntry::Unwrap<PhoneCallHistoryEntry>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallHistoryEntry(Local<Object> exports)
  {
    PhoneCallHistoryEntry::Init(exports);
  }

  class PhoneCallHistoryEntryReader : 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>("PhoneCallHistoryEntryReader").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
                  
      Nan::SetPrototypeMethod(localRef, "readBatchAsync", ReadBatchAsync);
      
                  
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryReader").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallHistoryEntryReader(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ 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::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^) 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());

      PhoneCallHistoryEntryReader *wrapperInstance = new PhoneCallHistoryEntryReader(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::ApplicationModel::Calls::PhoneCallHistoryEntryReader^>(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::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallHistoryEntryReader(winRtInstance));
    }


    static void ReadBatchAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryEntryReader *wrapper = PhoneCallHistoryEntryReader::Unwrap<PhoneCallHistoryEntryReader>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Foundation::Collections::IVectorView<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^>^ op;
    

      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->ReadBatchAsync();
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Foundation::Collections::IVectorView<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = NodeRT::Collections::VectorViewWrapper<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>::CreateVectorViewWrapper(result, 
            [](::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ val) -> Local<Value> {
              return WrapPhoneCallHistoryEntry(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(value);
            },
            [](Local<Value> value) -> ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ {
              return UnwrapPhoneCallHistoryEntry(value);
            }
          );
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
  





  private:
    ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallHistoryEntryReader(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ UnwrapPhoneCallHistoryEntryReader(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallHistoryEntryReader::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallHistoryEntryReader(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ 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>(PhoneCallHistoryEntryReader::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ UnwrapPhoneCallHistoryEntryReader(Local<Value> value)
  {
     return PhoneCallHistoryEntryReader::Unwrap<PhoneCallHistoryEntryReader>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallHistoryEntryReader(Local<Object> exports)
  {
    PhoneCallHistoryEntryReader::Init(exports);
  }

  class PhoneCallHistoryEntryQueryOptions : 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>("PhoneCallHistoryEntryQueryOptions").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("desiredMedia").ToLocalChecked(), DesiredMediaGetter, DesiredMediaSetter);
      Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceIds").ToLocalChecked(), SourceIdsGetter);
      
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallHistoryEntryQueryOptions").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallHistoryEntryQueryOptions(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ 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::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^) NodeRT::Utils::GetObjectInstance(info[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
      else if (info.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions();
        }
        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());

      PhoneCallHistoryEntryQueryOptions *wrapperInstance = new PhoneCallHistoryEntryQueryOptions(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::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^>(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::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallHistoryEntryQueryOptions(winRtInstance));
    }


  



    static void DesiredMediaGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryQueryOptions *wrapper = PhoneCallHistoryEntryQueryOptions::Unwrap<PhoneCallHistoryEntryQueryOptions>(info.This());

      try 
      {
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia result = wrapper->_instance->DesiredMedia;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    
    static void DesiredMediaSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryQueryOptions *wrapper = PhoneCallHistoryEntryQueryOptions::Unwrap<PhoneCallHistoryEntryQueryOptions>(info.This());

      try 
      {
        
        ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia winRtValue = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryDesiredMedia>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->DesiredMedia = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static void SourceIdsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryEntryQueryOptions *wrapper = PhoneCallHistoryEntryQueryOptions::Unwrap<PhoneCallHistoryEntryQueryOptions>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVector<::Platform::String^>^ result = wrapper->_instance->SourceIds;
        info.GetReturnValue().Set(NodeRT::Collections::VectorWrapper<::Platform::String^>::CreateVectorWrapper(result, 
            [](::Platform::String^ val) -> Local<Value> {
              return NodeRT::Utils::NewString(val->Data());
            },
            [](Local<Value> value) -> bool {
              return value->IsString();
            },
            [](Local<Value> value) -> ::Platform::String^ {
              return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
            }
          ));
        return;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
    


  private:
    ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallHistoryEntryQueryOptions(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ UnwrapPhoneCallHistoryEntryQueryOptions(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallHistoryEntryQueryOptions::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallHistoryEntryQueryOptions(::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ 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>(PhoneCallHistoryEntryQueryOptions::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ UnwrapPhoneCallHistoryEntryQueryOptions(Local<Value> value)
  {
     return PhoneCallHistoryEntryQueryOptions::Unwrap<PhoneCallHistoryEntryQueryOptions>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallHistoryEntryQueryOptions(Local<Object> exports)
  {
    PhoneCallHistoryEntryQueryOptions::Init(exports);
  }

  class PhoneCallHistoryStore : 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>("PhoneCallHistoryStore").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
            
      Nan::SetPrototypeMethod(localRef, "getEntryReader", GetEntryReader);
      
            
      Nan::SetPrototypeMethod(localRef, "getEntryAsync", GetEntryAsync);
      Nan::SetPrototypeMethod(localRef, "saveEntryAsync", SaveEntryAsync);
      Nan::SetPrototypeMethod(localRef, "deleteEntryAsync", DeleteEntryAsync);
      Nan::SetPrototypeMethod(localRef, "deleteEntriesAsync", DeleteEntriesAsync);
      Nan::SetPrototypeMethod(localRef, "markEntryAsSeenAsync", MarkEntryAsSeenAsync);
      Nan::SetPrototypeMethod(localRef, "markEntriesAsSeenAsync", MarkEntriesAsSeenAsync);
      Nan::SetPrototypeMethod(localRef, "getUnseenCountAsync", GetUnseenCountAsync);
      Nan::SetPrototypeMethod(localRef, "markAllAsSeenAsync", MarkAllAsSeenAsync);
      Nan::SetPrototypeMethod(localRef, "getSourcesUnseenCountAsync", GetSourcesUnseenCountAsync);
      Nan::SetPrototypeMethod(localRef, "markSourcesAsSeenAsync", MarkSourcesAsSeenAsync);
      
                  
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);


      Nan::Set(exports, Nan::New<String>("PhoneCallHistoryStore").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallHistoryStore(::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ 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::ApplicationModel::Calls::PhoneCallHistoryStore^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^) 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());

      PhoneCallHistoryStore *wrapperInstance = new PhoneCallHistoryStore(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::ApplicationModel::Calls::PhoneCallHistoryStore^>(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::ApplicationModel::Calls::PhoneCallHistoryStore^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallHistoryStore(winRtInstance));
    }


    static void GetEntryAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^ op;
    

      if (info.Length() == 2
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(info[0])));
          
          op = wrapper->_instance->GetEntryAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = WrapPhoneCallHistoryEntry(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void SaveEntryAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info[0]))
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ arg0 = UnwrapPhoneCallHistoryEntry(info[0]);
          
          op = wrapper->_instance->SaveEntryAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void DeleteEntryAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info[0]))
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ arg0 = UnwrapPhoneCallHistoryEntry(info[0]);
          
          op = wrapper->_instance->DeleteEntryAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void DeleteEntriesAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 2
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^>(info[0]) || info[0]->IsArray()))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(value);
                 },
                 [](Local<Value> value) -> ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ {
                   return UnwrapPhoneCallHistoryEntry(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          
          op = wrapper->_instance->DeleteEntriesAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void MarkEntryAsSeenAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(info[0]))
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ arg0 = UnwrapPhoneCallHistoryEntry(info[0]);
          
          op = wrapper->_instance->MarkEntryAsSeenAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void MarkEntriesAsSeenAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 2
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^>(info[0]) || info[0]->IsArray()))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>(value);
                 },
                 [](Local<Value> value) -> ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^ {
                   return UnwrapPhoneCallHistoryEntry(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntry^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          
          op = wrapper->_instance->MarkEntriesAsSeenAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void GetUnseenCountAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncOperation<unsigned int>^ op;
    

      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->GetUnseenCountAsync();
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<unsigned int> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = Nan::New<Integer>(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void MarkAllAsSeenAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->MarkAllAsSeenAsync();
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void GetSourcesUnseenCountAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncOperation<unsigned int>^ op;
    

      if (info.Length() == 2
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Platform::String^>^>(info[0]) || info[0]->IsArray()))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Platform::String^>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Platform::String^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Platform::String^>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return (!NodeRT::Utils::IsWinRtWrapper(value));
                 },
                 [](Local<Value> value) -> ::Platform::String^ {
                   return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Platform::String^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          
          op = wrapper->_instance->GetSourcesUnseenCountAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<unsigned int> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = Nan::New<Integer>(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
    static void MarkSourcesAsSeenAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (info.Length() == 2
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Platform::String^>^>(info[0]) || info[0]->IsArray()))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Platform::String^>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Platform::String^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Platform::String^>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return (!NodeRT::Utils::IsWinRtWrapper(value));
                 },
                 [](Local<Value> value) -> ::Platform::String^ {
                   return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Platform::String^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          
          op = wrapper->_instance->MarkSourcesAsSeenAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};

		    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }
  
    static void GetEntryReader(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>(info.This()))
      {
        return;
      }

      PhoneCallHistoryStore *wrapper = PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ result;
          result = wrapper->_instance->GetEntryReader();
          info.GetReturnValue().Set(WrapPhoneCallHistoryEntryReader(result));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
      else if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^>(info[0]))
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryQueryOptions^ arg0 = UnwrapPhoneCallHistoryEntryQueryOptions(info[0]);
          
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryEntryReader^ result;
          result = wrapper->_instance->GetEntryReader(arg0);
          info.GetReturnValue().Set(WrapPhoneCallHistoryEntryReader(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::ApplicationModel::Calls::PhoneCallHistoryStore^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallHistoryStore(::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ UnwrapPhoneCallHistoryStore(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallHistoryStore::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallHistoryStore(::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ 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>(PhoneCallHistoryStore::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^ UnwrapPhoneCallHistoryStore(Local<Value> value)
  {
     return PhoneCallHistoryStore::Unwrap<PhoneCallHistoryStore>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallHistoryStore(Local<Object> exports)
  {
    PhoneCallHistoryStore::Init(exports);
  }

  class PhoneCallHistoryManager : 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>("PhoneCallHistoryManager").ToLocalChecked());
      localRef->InstanceTemplate()->SetInternalFieldCount(1);
      
      Local<Function> func;
      Local<FunctionTemplate> funcTemplate;
                              
      Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
	  Nan::SetMethod(constructor, "castFrom", CastFrom);

      func = Nan::GetFunction(Nan::New<FunctionTemplate>(RequestStoreAsync)).ToLocalChecked();
      Nan::Set(constructor, Nan::New<String>("requestStoreAsync").ToLocalChecked(), func);

      Nan::Set(exports, Nan::New<String>("PhoneCallHistoryManager").ToLocalChecked(), constructor);
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    PhoneCallHistoryManager(::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ 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::ApplicationModel::Calls::PhoneCallHistoryManager^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^>(info[0]))
      {
        try 
        {
          winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^) 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());

      PhoneCallHistoryManager *wrapperInstance = new PhoneCallHistoryManager(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::ApplicationModel::Calls::PhoneCallHistoryManager^>(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::ApplicationModel::Calls::PhoneCallHistoryManager^ winRtInstance;
		try
		{
			winRtInstance = (::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^) NodeRT::Utils::GetObjectInstance(info[0]);
		}
		catch (Platform::Exception ^exception)
		{
			NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
			return;
		}

		info.GetReturnValue().Set(WrapPhoneCallHistoryManager(winRtInstance));
    }


  

    static void RequestStoreAsync(Nan::NAN_METHOD_ARGS_TYPE info)
    {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction())
      {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return;
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^>^ op;
      

      if (info.Length() == 2
        && info[0]->IsInt32())
      {
        try
        {
          ::Windows::ApplicationModel::Calls::PhoneCallHistoryStoreAccessType arg0 = static_cast<::Windows::ApplicationModel::Calls::PhoneCallHistoryStoreAccessType>(Nan::To<int32_t>(info[0]).FromMaybe(0));
          
          op = ::Windows::ApplicationModel::Calls::PhoneCallHistoryManager::RequestStoreAsync(arg0);
        }
        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;
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::ApplicationModel::Calls::PhoneCallHistoryStore^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Local<Value> error; 
            Local<Value> arg1 = WrapPhoneCallHistoryStore(result);
            if (tryCatch.HasCaught())
            {
              error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Local<Value> args[] = {error, arg1};
			// TODO: this is ugly! Needed due to the possibility of expception occuring inside object convertors
			// can be fixed by wrapping the conversion code in a function and calling it on the fly
			// we must clear the try catch block here so the invoked inner method exception won't get swollen (issue #52) 
			tryCatch.~TryCatch();

	  	    
            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });
    }




  private:
    ::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Local<v8::Value> WrapPhoneCallHistoryManager(::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ wintRtInstance);
    friend ::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ UnwrapPhoneCallHistoryManager(Local<Value> value);
  };
  Persistent<FunctionTemplate> PhoneCallHistoryManager::s_constructorTemplate;

  v8::Local<v8::Value> WrapPhoneCallHistoryManager(::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ 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>(PhoneCallHistoryManager::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::ApplicationModel::Calls::PhoneCallHistoryManager^ UnwrapPhoneCallHistoryManager(Local<Value> value)
  {
     return PhoneCallHistoryManager::Unwrap<PhoneCallHistoryManager>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitPhoneCallHistoryManager(Local<Object> exports)
  {
    PhoneCallHistoryManager::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::ApplicationModel::Calls::InitPhoneNetworkStateEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneVoicemailTypeEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallMediaEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineTransportEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneSimStateEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneAudioRoutingEndpointEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineWatcherStatusEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineNetworkOperatorDisplayTextLocationEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitCellularDtmfModeEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitVoipPhoneCallMediaEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitVoipPhoneCallRejectReasonEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitVoipPhoneCallStateEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitVoipPhoneCallResourceReservationStatusEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryOtherAppReadAccessEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryMediaEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryRawAddressKindEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryQueryDesiredMediaEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryStoreAccessTypeEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistorySourceIdKindEnum(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLine(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneVoicemail(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineCellularDetails(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallVideoCapabilities(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineConfiguration(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneDialOptions(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineWatcher(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneLineWatcherEventArgs(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallStore(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallManager(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallVideoCapabilitiesManager(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallBlocking(target);
  NodeRT::Windows::ApplicationModel::Calls::InitCallStateChangeEventArgs(target);
  NodeRT::Windows::ApplicationModel::Calls::InitCallAnswerEventArgs(target);
  NodeRT::Windows::ApplicationModel::Calls::InitCallRejectEventArgs(target);
  NodeRT::Windows::ApplicationModel::Calls::InitVoipPhoneCall(target);
  NodeRT::Windows::ApplicationModel::Calls::InitMuteChangeEventArgs(target);
  NodeRT::Windows::ApplicationModel::Calls::InitVoipCallCoordinator(target);
  NodeRT::Windows::ApplicationModel::Calls::InitLockScreenCallEndCallDeferral(target);
  NodeRT::Windows::ApplicationModel::Calls::InitLockScreenCallUI(target);
  NodeRT::Windows::ApplicationModel::Calls::InitLockScreenCallEndRequestedEventArgs(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryAddress(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntry(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryReader(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryEntryQueryOptions(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryStore(target);
  NodeRT::Windows::ApplicationModel::Calls::InitPhoneCallHistoryManager(target);

  NodeRT::Utils::RegisterNameSpace("Windows.ApplicationModel.Calls", target);
}


NODE_MODULE(binding, init)