text:
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#import "FBSDKAppEvents.h"
#import "FBSDKAppEvents+Internal.h"

#import <objc/runtime.h>

#import <UIKit/UIApplication.h>

#import "FBSDKAccessToken.h"
#import "FBSDKAppEventsState.h"
#import "FBSDKAppEventsStateManager.h"
#import "FBSDKAppEventsUtility.h"
#import "FBSDKConstants.h"
#import "FBSDKDynamicFrameworkLoader.h"
#import "FBSDKError.h"
#import "FBSDKGraphRequest+Internal.h"
#import "FBSDKInternalUtility.h"
#import "FBSDKLogger.h"
#import "FBSDKPaymentObserver.h"
#import "FBSDKServerConfiguration.h"
#import "FBSDKServerConfigurationManager.h"
#import "FBSDKSettings.h"
#import "FBSDKTimeSpentData.h"
#import "FBSDKUtility.h"
#import "FBSDKUserDataStore.h"

#if !TARGET_OS_TV
#import "FBSDKEventBindingManager.h"
#import "FBSDKHybridAppEventsScriptMessageHandler.h"
#endif

//
// Public event names
//

// General purpose
NSString *const FBSDKAppEventNameCompletedRegistration   = @"fb_mobile_complete_registration";
NSString *const FBSDKAppEventNameViewedContent           = @"fb_mobile_content_view";
NSString *const FBSDKAppEventNameSearched                = @"fb_mobile_search";
NSString *const FBSDKAppEventNameRated                   = @"fb_mobile_rate";
NSString *const FBSDKAppEventNameCompletedTutorial       = @"fb_mobile_tutorial_completion";
NSString *const FBSDKAppEventNameContact                 = @"Contact";
NSString *const FBSDKAppEventNameCustomizeProduct        = @"CustomizeProduct";
NSString *const FBSDKAppEventNameDonate                  = @"Donate";
NSString *const FBSDKAppEventNameFindLocation            = @"FindLocation";
NSString *const FBSDKAppEventNameSchedule                = @"Schedule";
NSString *const FBSDKAppEventNameStartTrial              = @"StartTrial";
NSString *const FBSDKAppEventNameSubmitApplication       = @"SubmitApplication";
NSString *const FBSDKAppEventNameSubscribe               = @"Subscribe";
NSString *const FBSDKAppEventNameAdImpression            = @"AdImpression";
NSString *const FBSDKAppEventNameAdClick                 = @"AdClick";

// Ecommerce related
NSString *const FBSDKAppEventNameAddedToCart             = @"fb_mobile_add_to_cart";
NSString *const FBSDKAppEventNameAddedToWishlist         = @"fb_mobile_add_to_wishlist";
NSString *const FBSDKAppEventNameInitiatedCheckout       = @"fb_mobile_initiated_checkout";
NSString *const FBSDKAppEventNameAddedPaymentInfo        = @"fb_mobile_add_payment_info";
NSString *const FBSDKAppEventNameProductCatalogUpdate    = @"fb_mobile_catalog_update";

// Gaming related
NSString *const FBSDKAppEventNameAchievedLevel           = @"fb_mobile_level_achieved";
NSString *const FBSDKAppEventNameUnlockedAchievement     = @"fb_mobile_achievement_unlocked";
NSString *const FBSDKAppEventNameSpentCredits            = @"fb_mobile_spent_credits";

//
// Public event parameter names
//

NSString *const FBSDKAppEventParameterNameCurrency               = @"fb_currency";
NSString *const FBSDKAppEventParameterNameRegistrationMethod     = @"fb_registration_method";
NSString *const FBSDKAppEventParameterNameContentType            = @"fb_content_type";
NSString *const FBSDKAppEventParameterNameContent                = @"fb_content";
NSString *const FBSDKAppEventParameterNameContentID              = @"fb_content_id";
NSString *const FBSDKAppEventParameterNameSearchString           = @"fb_search_string";
NSString *const FBSDKAppEventParameterNameSuccess                = @"fb_success";
NSString *const FBSDKAppEventParameterNameMaxRatingValue         = @"fb_max_rating_value";
NSString *const FBSDKAppEventParameterNamePaymentInfoAvailable   = @"fb_payment_info_available";
NSString *const FBSDKAppEventParameterNameNumItems               = @"fb_num_items";
NSString *const FBSDKAppEventParameterNameLevel                  = @"fb_level";
NSString *const FBSDKAppEventParameterNameDescription            = @"fb_description";
NSString *const FBSDKAppEventParameterLaunchSource               = @"fb_mobile_launch_source";
NSString *const FBSDKAppEventParameterNameAdType                 = @"ad_type";
NSString *const FBSDKAppEventParameterNameOrderID                = @"fb_order_id";

//
// Public event parameter names for DPA Catalog
//

NSString *const FBSDKAppEventParameterProductCustomLabel0               = @"fb_product_custom_label_0";
NSString *const FBSDKAppEventParameterProductCustomLabel1               = @"fb_product_custom_label_1";
NSString *const FBSDKAppEventParameterProductCustomLabel2               = @"fb_product_custom_label_2";
NSString *const FBSDKAppEventParameterProductCustomLabel3               = @"fb_product_custom_label_3";
NSString *const FBSDKAppEventParameterProductCustomLabel4               = @"fb_product_custom_label_4";
NSString *const FBSDKAppEventParameterProductAppLinkIOSUrl              = @"fb_product_applink_ios_url";
NSString *const FBSDKAppEventParameterProductAppLinkIOSAppStoreID       = @"fb_product_applink_ios_app_store_id";
NSString *const FBSDKAppEventParameterProductAppLinkIOSAppName          = @"fb_product_applink_ios_app_name";
NSString *const FBSDKAppEventParameterProductAppLinkIPhoneUrl           = @"fb_product_applink_iphone_url";
NSString *const FBSDKAppEventParameterProductAppLinkIPhoneAppStoreID    = @"fb_product_applink_iphone_app_store_id";
NSString *const FBSDKAppEventParameterProductAppLinkIPhoneAppName       = @"fb_product_applink_iphone_app_name";
NSString *const FBSDKAppEventParameterProductAppLinkIPadUrl             = @"fb_product_applink_ipad_url";
NSString *const FBSDKAppEventParameterProductAppLinkIPadAppStoreID      = @"fb_product_applink_ipad_app_store_id";
NSString *const FBSDKAppEventParameterProductAppLinkIPadAppName         = @"fb_product_applink_ipad_app_name";
NSString *const FBSDKAppEventParameterProductAppLinkAndroidUrl          = @"fb_product_applink_android_url";
NSString *const FBSDKAppEventParameterProductAppLinkAndroidPackage      = @"fb_product_applink_android_package";
NSString *const FBSDKAppEventParameterProductAppLinkAndroidAppName      = @"fb_product_applink_android_app_name";
NSString *const FBSDKAppEventParameterProductAppLinkWindowsPhoneUrl     = @"fb_product_applink_windows_phone_url";
NSString *const FBSDKAppEventParameterProductAppLinkWindowsPhoneAppID   = @"fb_product_applink_windows_phone_app_id";
NSString *const FBSDKAppEventParameterProductAppLinkWindowsPhoneAppName = @"fb_product_applink_windows_phone_app_name";

//
// Public event parameter values
//

NSString *const FBSDKAppEventParameterValueNo                    = @"0";
NSString *const FBSDKAppEventParameterValueYes                   = @"1";

//
// Event names internal to this file
//
NSString *const FBSDKAppEventNamePurchased        = @"fb_mobile_purchase";

NSString *const FBSDKAppEventNameLoginViewUsage                   = @"fb_login_view_usage";
NSString *const FBSDKAppEventNameShareSheetLaunch                 = @"fb_share_sheet_launch";
NSString *const FBSDKAppEventNameShareSheetDismiss                = @"fb_share_sheet_dismiss";
NSString *const FBSDKAppEventNameShareTrayDidLaunch               = @"fb_share_tray_did_launch";
NSString *const FBSDKAppEventNameShareTrayDidSelectActivity       = @"fb_share_tray_did_select_activity";
NSString *const FBSDKAppEventNamePermissionsUILaunch              = @"fb_permissions_ui_launch";
NSString *const FBSDKAppEventNamePermissionsUIDismiss             = @"fb_permissions_ui_dismiss";
NSString *const FBSDKAppEventNameFBDialogsPresentShareDialog      = @"fb_dialogs_present_share";
NSString *const FBSDKAppEventNameFBDialogsPresentShareDialogPhoto = @"fb_dialogs_present_share_photo";
NSString *const FBSDKAppEventNameFBDialogsPresentShareDialogOG    = @"fb_dialogs_present_share_og";
NSString *const FBSDKAppEventNameFBDialogsPresentLikeDialogOG     = @"fb_dialogs_present_like_og";
NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialog      = @"fb_dialogs_present_message";
NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialogPhoto = @"fb_dialogs_present_message_photo";
NSString *const FBSDKAppEventNameFBDialogsPresentMessageDialogOG    = @"fb_dialogs_present_message_og";

NSString *const FBSDKAppEventNameFBDialogsNativeLoginDialogStart  = @"fb_dialogs_native_login_dialog_start";
NSString *const FBSDKAppEventsNativeLoginDialogStartTime          = @"fb_native_login_dialog_start_time";

NSString *const FBSDKAppEventNameFBDialogsNativeLoginDialogEnd    = @"fb_dialogs_native_login_dialog_end";
NSString *const FBSDKAppEventsNativeLoginDialogEndTime            = @"fb_native_login_dialog_end_time";

NSString *const FBSDKAppEventNameFBDialogsWebLoginCompleted       = @"fb_dialogs_web_login_dialog_complete";
NSString *const FBSDKAppEventsWebLoginE2E                         = @"fb_web_login_e2e";

NSString *const FBSDKAppEventNameFBSessionAuthStart               = @"fb_mobile_login_start";
NSString *const FBSDKAppEventNameFBSessionAuthEnd                 = @"fb_mobile_login_complete";
NSString *const FBSDKAppEventNameFBSessionAuthMethodStart         = @"fb_mobile_login_method_start";
NSString *const FBSDKAppEventNameFBSessionAuthMethodEnd           = @"fb_mobile_login_method_complete";

NSString *const FBSDKAppEventNameFBSDKLikeButtonImpression        = @"fb_like_button_impression";
NSString *const FBSDKAppEventNameFBSDKLoginButtonImpression       = @"fb_login_button_impression";
NSString *const FBSDKAppEventNameFBSDKSendButtonImpression        = @"fb_send_button_impression";
NSString *const FBSDKAppEventNameFBSDKShareButtonImpression       = @"fb_share_button_impression";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonImpression = @"fb_live_streaming_button_impression";

NSString *const FBSDKAppEventNameFBSDKSmartLoginService      = @"fb_smart_login_service";

NSString *const FBSDKAppEventNameFBSDKLikeButtonDidTap  = @"fb_like_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKLoginButtonDidTap  = @"fb_login_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKSendButtonDidTap  = @"fb_send_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKShareButtonDidTap  = @"fb_share_button_did_tap";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingButtonDidTap  = @"fb_live_streaming_button_did_tap";

NSString *const FBSDKAppEventNameFBSDKLikeControlDidDisable          = @"fb_like_control_did_disable";
NSString *const FBSDKAppEventNameFBSDKLikeControlDidLike             = @"fb_like_control_did_like";
NSString *const FBSDKAppEventNameFBSDKLikeControlDidPresentDialog    = @"fb_like_control_did_present_dialog";
NSString *const FBSDKAppEventNameFBSDKLikeControlDidTap              = @"fb_like_control_did_tap";
NSString *const FBSDKAppEventNameFBSDKLikeControlDidUnlike           = @"fb_like_control_did_unlike";
NSString *const FBSDKAppEventNameFBSDKLikeControlError               = @"fb_like_control_error";
NSString *const FBSDKAppEventNameFBSDKLikeControlImpression          = @"fb_like_control_impression";
NSString *const FBSDKAppEventNameFBSDKLikeControlNetworkUnavailable  = @"fb_like_control_network_unavailable";

NSString *const FBSDLAppEventNameFBSDKEventShareDialogResult =              @"fb_dialog_share_result";
NSString *const FBSDKAppEventNameFBSDKEventMessengerShareDialogResult =     @"fb_messenger_dialog_share_result";
NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogResult =     @"fb_app_invite_dialog_share_result";

NSString *const FBSDKAppEventNameFBSDKEventShareDialogShow =            @"fb_dialog_share_show";
NSString *const FBSDKAppEventNameFBSDKEventMessengerShareDialogShow =   @"fb_messenger_dialog_share_show";
NSString *const FBSDKAppEventNameFBSDKEventAppInviteShareDialogShow =   @"fb_app_invite_share_show";

NSString *const FBSDKAppEventNameFBSessionFASLoginDialogResult = @"fb_mobile_login_fas_dialog_result";

NSString *const FBSDKAppEventNameFBSDKLiveStreamingStart        = @"fb_sdk_live_streaming_start";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingStop         = @"fb_sdk_live_streaming_stop";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingPause        = @"fb_sdk_live_streaming_pause";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingResume       = @"fb_sdk_live_streaming_resume";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingError        = @"fb_sdk_live_streaming_error";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingUpdateStatus = @"fb_sdk_live_streaming_update_status";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingVideoID      = @"fb_sdk_live_streaming_video_id";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingMic          = @"fb_sdk_live_streaming_mic";
NSString *const FBSDKAppEventNameFBSDKLiveStreamingCamera       = @"fb_sdk_live_streaming_camera";

// Event Parameters internal to this file
NSString *const FBSDKAppEventParameterDialogOutcome               = @"fb_dialog_outcome";
NSString *const FBSDKAppEventParameterDialogErrorMessage          = @"fb_dialog_outcome_error_message";
NSString *const FBSDKAppEventParameterDialogMode                  = @"fb_dialog_mode";
NSString *const FBSDKAppEventParameterDialogShareContentType      = @"fb_dialog_share_content_type";
NSString *const FBSDKAppEventParameterDialogShareContentUUID      = @"fb_dialog_share_content_uuid";
NSString *const FBSDKAppEventParameterDialogShareContentPageID    = @"fb_dialog_share_content_page_id";
NSString *const FBSDKAppEventParameterShareTrayActivityName       = @"fb_share_tray_activity";
NSString *const FBSDKAppEventParameterShareTrayResult             = @"fb_share_tray_result";
NSString *const FBSDKAppEventParameterLogTime = @"_logTime";
NSString *const FBSDKAppEventParameterEventName = @"_eventName";
NSString *const FBSDKAppEventParameterImplicitlyLogged = @"_implicitlyLogged";

NSString *const FBSDKAppEventParameterLiveStreamingPrevStatus    = @"live_streaming_prev_status";
NSString *const FBSDKAppEventParameterLiveStreamingStatus        = @"live_streaming_status";
NSString *const FBSDKAppEventParameterLiveStreamingError         = @"live_streaming_error";
NSString *const FBSDKAppEventParameterLiveStreamingVideoID       = @"live_streaming_video_id";
NSString *const FBSDKAppEventParameterLiveStreamingMicEnabled    = @"live_streaming_mic_enabled";
NSString *const FBSDKAppEventParameterLiveStreamingCameraEnabled = @"live_streaming_camera_enabled";

NSString *const FBSDKAppEventParameterProductItemID              = @"fb_product_item_id";
NSString *const FBSDKAppEventParameterProductAvailability        = @"fb_product_availability";
NSString *const FBSDKAppEventParameterProductCondition           = @"fb_product_condition";
NSString *const FBSDKAppEventParameterProductDescription         = @"fb_product_description";
NSString *const FBSDKAppEventParameterProductImageLink           = @"fb_product_image_link";
NSString *const FBSDKAppEventParameterProductLink                = @"fb_product_link";
NSString *const FBSDKAppEventParameterProductTitle               = @"fb_product_title";
NSString *const FBSDKAppEventParameterProductGTIN                = @"fb_product_gtin";
NSString *const FBSDKAppEventParameterProductMPN                 = @"fb_product_mpn";
NSString *const FBSDKAppEventParameterProductBrand               = @"fb_product_brand";
NSString *const FBSDKAppEventParameterProductPriceAmount         = @"fb_product_price_amount";
NSString *const FBSDKAppEventParameterProductPriceCurrency       = @"fb_product_price_currency";

// Event parameter values internal to this file
NSString *const FBSDKAppEventsDialogOutcomeValue_Completed = @"Completed";
NSString *const FBSDKAppEventsDialogOutcomeValue_Cancelled = @"Cancelled";
NSString *const FBSDKAppEventsDialogOutcomeValue_Failed    = @"Failed";

NSString *const FBSDKAppEventsDialogShareModeAutomatic      = @"Automatic";
NSString *const FBSDKAppEventsDialogShareModeBrowser        = @"Browser";
NSString *const FBSDKAppEventsDialogShareModeNative         = @"Native";
NSString *const FBSDKAppEventsDialogShareModeShareSheet     = @"ShareSheet";
NSString *const FBSDKAppEventsDialogShareModeWeb            = @"Web";
NSString *const FBSDKAppEventsDialogShareModeFeedBrowser    = @"FeedBrowser";
NSString *const FBSDKAppEventsDialogShareModeFeedWeb        = @"FeedWeb";
NSString *const FBSDKAppEventsDialogShareModeUnknown        = @"Unknown";

NSString *const FBSDKAppEventsDialogShareContentTypeOpenGraph                         = @"OpenGraph";
NSString *const FBSDKAppEventsDialogShareContentTypeStatus                            = @"Status";
NSString *const FBSDKAppEventsDialogShareContentTypePhoto                             = @"Photo";
NSString *const FBSDKAppEventsDialogShareContentTypeVideo                             = @"Video";
NSString *const FBSDKAppEventsDialogShareContentTypeCamera                            = @"Camera";
NSString *const FBSDKAppEventsDialogShareContentTypeMessengerGenericTemplate          = @"GenericTemplate";
NSString *const FBSDKAppEventsDialogShareContentTypeMessengerMediaTemplate            = @"MediaTemplate";
NSString *const FBSDKAppEventsDialogShareContentTypeMessengerOpenGraphMusicTemplate   = @"OpenGraphMusicTemplate";
NSString *const FBSDKAppEventsDialogShareContentTypeUnknown                           = @"Unknown";

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0

NSNotificationName const FBSDKAppEventsLoggingResultNotification = @"com.facebook.sdk:FBSDKAppEventsLoggingResultNotification";

#else

NSString *const FBSDKAppEventsLoggingResultNotification = @"com.facebook.sdk:FBSDKAppEventsLoggingResultNotification";

#endif

NSString *const FBSDKAppEventsOverrideAppIDBundleKey = @"FacebookLoggingOverrideAppID";

//
// Push Notifications
//
// Activities Endpoint Parameter
static NSString *const FBSDKActivitesParameterPushDeviceToken = @"device_token";
// Event Names
static NSString *const FBSDKAppEventNamePushTokenObtained = @"fb_mobile_obtain_push_token";
static NSString *const FBSDKAppEventNamePushOpened = @"fb_mobile_push_opened";
// Event Parameter
static NSString *const FBSDKAppEventParameterPushCampaign = @"fb_push_campaign";
static NSString *const FBSDKAppEventParameterPushAction = @"fb_push_action";
// Payload Keys
static NSString *const FBSDKAppEventsPushPayloadKey = @"fb_push_payload";
static NSString *const FBSDKAppEventsPushPayloadCampaignKey = @"campaign";

//
// Augmentation of web browser constants
//
NSString *const FBSDKAppEventsWKWebViewMessagesPixelIDKey = @"pixelID";
NSString *const FBSDKAppEventsWKWebViewMessagesHandlerKey = @"fbmqHandler";
NSString *const FBSDKAppEventsWKWebViewMessagesEventKey = @"event";
NSString *const FBSDKAppEventsWKWebViewMessagesParamsKey = @"params";
NSString *const FBSDKAPPEventsWKWebViewMessagesProtocolKey = @"fbmq-0.1";

#define NUM_LOG_EVENTS_TO_TRY_TO_FLUSH_AFTER 100
#define FLUSH_PERIOD_IN_SECONDS 15
#define USER_ID_USER_DEFAULTS_KEY @"com.facebook.sdk.appevents.userid"

#define FBUnityUtilityClassName "FBUnityUtility"
#define FBUnityUtilityUpdateBindingsSelector @"triggerUpdateBindings:"

#define UNINSTALL_TRACKING_DEVICE_ID_KEY          @"device_id"
#define UNINSTALL_TRACKING_PLATFORM_KEY           @"platform"
#define UNINSTALL_TRACKING_DEVICE_TOKEN_KEY       @"device_token"
#define UNINSTALL_TRACKING_TOKEN_ENDPOINT         @"app_push_device_token"

static NSString *g_overrideAppID = nil;

@interface FBSDKAppEvents ()

@property (nonatomic, assign) FBSDKAppEventsFlushBehavior flushBehavior;
//for testing only.
@property (nonatomic, assign) BOOL disableTimer;

@property (nonatomic, copy) NSString *pushNotificationsDeviceTokenString;

@property (nonatomic, strong) dispatch_source_t flushTimer;

@end

@implementation FBSDKAppEvents
{
  BOOL _explicitEventsLoggedYet;
  FBSDKServerConfiguration *_serverConfiguration;
  FBSDKAppEventsState *_appEventsState;
#if !TARGET_OS_TV
  FBSDKEventBindingManager *_eventBindingManager;
#endif
  NSString *_userID;
  BOOL _isUnityInit;
}

#pragma mark - Object Lifecycle

+ (void)initialize
{
  if (self == [FBSDKAppEvents class]) {
    g_overrideAppID = [[[NSBundle mainBundle] objectForInfoDictionaryKey:FBSDKAppEventsOverrideAppIDBundleKey] copy];
  }
}

- (FBSDKAppEvents *)init
{
  self = [super init];
  if (self) {
    _flushBehavior = FBSDKAppEventsFlushBehaviorAuto;

    typeof(self) __weak weakSelf = self;
    self.flushTimer = [FBSDKUtility startGCDTimerWithInterval:FLUSH_PERIOD_IN_SECONDS
                                                        block:^{
                                                          [weakSelf flushTimerFired:nil];
                                                        }];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    _userID = [defaults stringForKey:USER_ID_USER_DEFAULTS_KEY];
    [self fetchServerConfiguration:nil];
  }

  return self;
}

- (void)registerNotifications {
  [[NSNotificationCenter defaultCenter]
   addObserver:self
   selector:@selector(applicationMovingFromActiveStateOrTerminating)
   name:UIApplicationWillResignActiveNotification
   object:NULL];

  [[NSNotificationCenter defaultCenter]
   addObserver:self
   selector:@selector(applicationMovingFromActiveStateOrTerminating)
   name:UIApplicationWillTerminateNotification
   object:NULL];

  [[NSNotificationCenter defaultCenter]
   addObserver:self
   selector:@selector(applicationDidBecomeActive)
   name:UIApplicationDidBecomeActiveNotification
   object:NULL];
}

- (void)dealloc
{
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  [FBSDKUtility stopGCDTimer:self.flushTimer];
}

#pragma mark - Public Methods

+ (void)logEvent:(NSString *)eventName
{
  [FBSDKAppEvents logEvent:eventName
                parameters:nil];
}

+ (void)logEvent:(NSString *)eventName
      valueToSum:(double)valueToSum
{
  [FBSDKAppEvents logEvent:eventName
                valueToSum:valueToSum
                parameters:nil];
}

+ (void)logEvent:(NSString *)eventName
      parameters:(NSDictionary *)parameters
{
  [FBSDKAppEvents logEvent:eventName
                valueToSum:nil
                parameters:parameters
               accessToken:nil];
}

+ (void)logEvent:(NSString *)eventName
      valueToSum:(double)valueToSum
      parameters:(NSDictionary *)parameters
{
  [FBSDKAppEvents logEvent:eventName
                valueToSum:@(valueToSum)
                parameters:parameters
               accessToken:nil];
}

+ (void)logEvent:(NSString *)eventName
      valueToSum:(NSNumber *)valueToSum
      parameters:(NSDictionary *)parameters
     accessToken:(FBSDKAccessToken *)accessToken
{
  [[FBSDKAppEvents singleton] instanceLogEvent:eventName
                                    valueToSum:valueToSum
                                    parameters:parameters
                            isImplicitlyLogged:(BOOL)parameters[FBSDKAppEventParameterImplicitlyLogged]
                                   accessToken:accessToken];
}

+ (void)logPurchase:(double)purchaseAmount
           currency:(NSString *)currency
{
  [FBSDKAppEvents logPurchase:purchaseAmount
                     currency:currency
                   parameters:nil];
}

+ (void)logPurchase:(double)purchaseAmount
           currency:(NSString *)currency
         parameters:(NSDictionary *)parameters
{
  [FBSDKAppEvents logPurchase:purchaseAmount
                     currency:currency
                   parameters:parameters
                  accessToken:nil];
}

+ (void)logPurchase:(double)purchaseAmount
           currency:(NSString *)currency
         parameters:(NSDictionary *)parameters
        accessToken:(FBSDKAccessToken *)accessToken
{

  // A purchase event is just a regular logged event with a given event name
  // and treating the currency value as going into the parameters dictionary.
  NSDictionary *newParameters;
  if (!parameters) {
    newParameters = @{ FBSDKAppEventParameterNameCurrency : currency };
  } else {
    newParameters = [NSMutableDictionary dictionaryWithDictionary:parameters];
    [newParameters setValue:currency forKey:FBSDKAppEventParameterNameCurrency];
  }

  [FBSDKAppEvents logEvent:FBSDKAppEventNamePurchased
                valueToSum:@(purchaseAmount)
                parameters:newParameters
               accessToken:accessToken];

  // Unless the behavior is set to only allow explicit flushing, we go ahead and flush, since purchase events
  // are relatively rare and relatively high value and worth getting across on wire right away.
  if ([FBSDKAppEvents flushBehavior] != FBSDKAppEventsFlushBehaviorExplicitOnly) {
    [[FBSDKAppEvents singleton] flushForReason:FBSDKAppEventsFlushReasonEagerlyFlushingEvent];
  }
}

/*
 * Push Notifications Logging
 */

+ (void)logPushNotificationOpen:(NSDictionary *)payload
{
  [self logPushNotificationOpen:payload action:nil];
}

+ (void)logPushNotificationOpen:(NSDictionary *)payload action:(NSString *)action
{
  NSDictionary *facebookPayload = payload[FBSDKAppEventsPushPayloadKey];
  if (!facebookPayload) {
    return;
  }
  NSString *campaign = facebookPayload[FBSDKAppEventsPushPayloadCampaignKey];
  if (campaign.length == 0) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"Malformed payload specified for logging a push notification open."];
    return;
  }

  NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithObject:campaign forKey:FBSDKAppEventParameterPushCampaign];
  if (action) {
    parameters[FBSDKAppEventParameterPushAction] = action;
  }
  [self logEvent:FBSDKAppEventNamePushOpened parameters:parameters];
}

/*
 *  Uploads product catalog product item as an app event
 */
+ (void)logProductItem:(NSString *)itemID
          availability:(FBSDKProductAvailability)availability
             condition:(FBSDKProductCondition)condition
           description:(NSString *)description
             imageLink:(NSString *)imageLink
                  link:(NSString *)link
                 title:(NSString *)title
           priceAmount:(double)priceAmount
              currency:(NSString *)currency
                  gtin:(NSString *)gtin
                   mpn:(NSString *)mpn
                 brand:(NSString *)brand
            parameters:(NSDictionary *)parameters {
  if (itemID == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"itemID cannot be null"];
    return;
  } else if (description == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"description cannot be null"];
    return;
  } else if (imageLink == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"imageLink cannot be null"];
    return;
  } else if (link == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"link cannot be null"];
    return;
  } else if (title == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"title cannot be null"];
    return;
  } else if (currency == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"currency cannot be null"];
    return;
  } else if (gtin == nil && mpn == nil && brand == nil) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
                           logEntry:@"Either gtin, mpn or brand is required"];
    return;
  }

  NSMutableDictionary *dict = [NSMutableDictionary dictionary];
  if (nil != parameters) {
    [dict setValuesForKeysWithDictionary:parameters];
  }

  dict[FBSDKAppEventParameterProductItemID] = itemID;

  NSString *avail = nil;
  switch (availability) {
    case FBSDKProductAvailabilityInStock:
      avail = @"IN_STOCK"; break;
    case FBSDKProductAvailabilityOutOfStock:
      avail = @"OUT_OF_STOCK"; break;
    case FBSDKProductAvailabilityPreOrder:
      avail = @"PREORDER"; break;
    case FBSDKProductAvailabilityAvailableForOrder:
      avail = @"AVALIABLE_FOR_ORDER"; break;
    case FBSDKProductAvailabilityDiscontinued:
      avail = @"DISCONTINUED"; break;
  }
  if (avail) {
    dict[FBSDKAppEventParameterProductAvailability] = avail;
  }

  NSString *cond = nil;
  switch (condition) {
    case FBSDKProductConditionNew:
      cond = @"NEW"; break;
    case FBSDKProductConditionRefurbished:
      cond = @"REFURBISHED"; break;
    case FBSDKProductConditionUsed:
      cond = @"USED"; break;
  }
  if (cond) {
    dict[FBSDKAppEventParameterProductCondition] = cond;
  }

  dict[FBSDKAppEventParameterProductDescription] = description;
  dict[FBSDKAppEventParameterProductImageLink] = imageLink;
  dict[FBSDKAppEventParameterProductLink] = link;
  dict[FBSDKAppEventParameterProductTitle] = title;
  dict[FBSDKAppEventParameterProductPriceAmount] = [NSString stringWithFormat:@"%.3lf", priceAmount];
  dict[FBSDKAppEventParameterProductPriceCurrency] = currency;
  if (gtin) {
    dict[FBSDKAppEventParameterProductGTIN] = gtin;
  }
  if (mpn) {
    dict[FBSDKAppEventParameterProductMPN] = mpn;
  }
  if (brand) {
    dict[FBSDKAppEventParameterProductBrand] = brand;
  }

  [FBSDKAppEvents logEvent:FBSDKAppEventNameProductCatalogUpdate
                parameters:dict];
}

+ (void)activateApp
{
  [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass(self)];

  // Fetch app settings and register for transaction notifications only if app supports implicit purchase
  // events
  FBSDKAppEvents *instance = [FBSDKAppEvents singleton];
  [instance publishInstall];
  [instance fetchServerConfiguration:NULL];

  // Restore time spent data, indicating that we're being called from "activateApp", which will,
  // when appropriate, result in logging an "activated app" and "deactivated app" (for the
  // previous session) App Event.
  [FBSDKTimeSpentData restore:YES];
  [FBSDKUserDataStore initStore];
}

+ (void)setPushNotificationsDeviceToken:(NSData *)deviceToken
{
  NSString *deviceTokenString = [FBSDKInternalUtility hexadecimalStringFromData:deviceToken];
  [FBSDKAppEvents setPushNotificationsDeviceTokenString:deviceTokenString];
}

+ (void)setPushNotificationsDeviceTokenString:(NSString *)deviceTokenString
{
  if (deviceTokenString == nil) {
    [FBSDKAppEvents singleton].pushNotificationsDeviceTokenString = nil;
    return;
  }

  if (![deviceTokenString isEqualToString:([FBSDKAppEvents singleton].pushNotificationsDeviceTokenString)]) {
    [FBSDKAppEvents singleton].pushNotificationsDeviceTokenString = deviceTokenString;

    [FBSDKAppEvents logEvent:FBSDKAppEventNamePushTokenObtained];

    // Unless the behavior is set to only allow explicit flushing, we go ahead and flush the event
    if ([FBSDKAppEvents flushBehavior] != FBSDKAppEventsFlushBehaviorExplicitOnly) {
      [[FBSDKAppEvents singleton] flushForReason:FBSDKAppEventsFlushReasonEagerlyFlushingEvent];
    }
  }
}

+ (FBSDKAppEventsFlushBehavior)flushBehavior
{
  return [FBSDKAppEvents singleton].flushBehavior;
}

+ (void)setFlushBehavior:(FBSDKAppEventsFlushBehavior)flushBehavior
{
  [FBSDKAppEvents singleton].flushBehavior = flushBehavior;
}

+ (NSString *)loggingOverrideAppID
{
  return g_overrideAppID;
}

+ (void)setLoggingOverrideAppID:(NSString *)appID
{
  if (![g_overrideAppID isEqualToString:appID]) {
    FBSDKConditionalLog(![FBSDKAppEvents singleton]->_explicitEventsLoggedYet,
                        FBSDKLoggingBehaviorDeveloperErrors,
                        @"[FBSDKAppEvents setLoggingOverrideAppID:] should only be called prior to any events being logged.");
    g_overrideAppID = appID;
  }
}

+ (void)flush
{
  [[FBSDKAppEvents singleton] flushForReason:FBSDKAppEventsFlushReasonExplicit];
}

+ (void)setUserID:(NSString *)userID
{
  if ([[[self class] singleton]->_userID isEqualToString:userID]) {
    return;
  }
  [[self class] singleton]->_userID = userID;
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setObject:userID forKey:USER_ID_USER_DEFAULTS_KEY];
  [defaults synchronize];
}

+ (void)clearUserID
{
  [self setUserID:nil];
}

+ (NSString *)userID
{
  return [[self class] singleton]->_userID;
}

+ (void)setUserData:(NSDictionary*)userData
{
  [FBSDKUserDataStore setUserDataAndHash:userData];
}

+ (void)setUserEmail:(NSString *)email
           firstName:(NSString *)firstName
            lastName:(NSString *)lastName
               phone:(NSString *)phone
         dateOfBirth:(NSString *)dateOfBirth
              gender:(NSString *)gender
                city:(NSString *)city
               state:(NSString *)state
                 zip:(NSString *)zip
             country:(NSString *)country
{
  [FBSDKUserDataStore setUserDataAndHash:email
                               firstName:firstName
                                lastName:lastName
                                   phone:phone
                             dateOfBirth:dateOfBirth
                                  gender:gender
                                    city:city
                                   state:state
                                     zip:zip
                                 country:country];
}

+ (NSString*)getUserData
{
  return [FBSDKUserDataStore getHashedUserData];
}

+ (void)clearUserData
{
  [FBSDKUserDataStore setUserDataAndHash:nil
                               firstName:nil
                                lastName:nil
                                   phone:nil
                             dateOfBirth:nil
                                  gender:nil
                                    city:nil
                                   state:nil
                                     zip:nil
                                 country:nil];
}

+ (void)updateUserProperties:(NSDictionary *)properties handler:(FBSDKGraphRequestHandler)handler
{
  NSString *userID = [[self class] userID];

  if (userID.length == 0) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Missing [FBSDKAppEvents userID] for [FBSDKAppEvents updateUserProperties:]"];
    NSError *error = [NSError fbRequiredArgumentErrorWithName:@"userID" message:@"Missing [FBSDKAppEvents userID] for [FBSDKAppEvents updateUserProperties:]"];
    if (handler) {
      handler(nil, nil, error);
    }
    return;
  }
  NSMutableDictionary *dataDictionary = [NSMutableDictionary dictionaryWithCapacity:3];
  dataDictionary[@"user_unique_id"] = [FBSDKAppEvents userID];
  [FBSDKInternalUtility dictionary:dataDictionary setObject:[FBSDKAppEventsUtility advertiserID] forKey:@"advertiser_id"];
  [FBSDKInternalUtility dictionary:dataDictionary setObject:properties forKey:@"custom_data"];

  NSError *error;
  __block NSError *invalidObjectError;
  NSString *dataJSONString = [FBSDKInternalUtility JSONStringForObject:@[dataDictionary] error:&error invalidObjectHandler:^id(id object, BOOL *stop) {
    *stop = YES;
    invalidObjectError = [NSError fbUnknownErrorWithMessage:@"The values in the properties dictionary must be NSStrings or NSNumbers"];
    return nil;
  }];
  if (!error) {
    error = invalidObjectError;
  }
  if (error) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Failed to serialize properties for [FBSDKAppEvents updateUserProperties:]"];
    if (handler) {
      handler(nil, nil, error);
    }
    return;
  }
  NSDictionary *params = @{ @"data" : dataJSONString };
  FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@/user_properties", [[self singleton] appID]]
                                                                 parameters:params
                                                                tokenString:[FBSDKAccessToken currentAccessToken].tokenString
                                                                 HTTPMethod:@"POST"
                                                                      flags:FBSDKGraphRequestFlagDisableErrorRecovery |
                                                                            FBSDKGraphRequestFlagDoNotInvalidateTokenOnError |
                                                                            FBSDKGraphRequestFlagSkipClientToken
                                ];
  [request startWithCompletionHandler:handler];
}

#if !TARGET_OS_TV
+ (void)augmentHybridWKWebView:(WKWebView *)webView {
  // Ensure we can instantiate WebKit before trying this
  Class WKWebViewClass = fbsdkdfl_WKWebViewClass();
  if (WKWebViewClass != nil && [webView isKindOfClass:WKWebViewClass]) {
    Class WKUserScriptClass = fbsdkdfl_WKUserScriptClass();
    if (WKUserScriptClass != nil) {
      WKUserContentController *controller = webView.configuration.userContentController;
      FBSDKHybridAppEventsScriptMessageHandler *scriptHandler = [[FBSDKHybridAppEventsScriptMessageHandler alloc] init];
      [controller addScriptMessageHandler:scriptHandler name:FBSDKAppEventsWKWebViewMessagesHandlerKey];

      NSString *js =  [NSString stringWithFormat:@"window.fbmq_%@={'sendEvent': function(pixel_id,event_name,custom_data){var msg={\"%@\":pixel_id, \"%@\":event_name,\"%@\":custom_data};window.webkit.messageHandlers[\"%@\"].postMessage(msg);}, 'getProtocol':function(){return \"%@\";}}",
                         [[self singleton] appID],
                         FBSDKAppEventsWKWebViewMessagesPixelIDKey,
                         FBSDKAppEventsWKWebViewMessagesEventKey,
                         FBSDKAppEventsWKWebViewMessagesParamsKey,
                         FBSDKAppEventsWKWebViewMessagesHandlerKey,
                         FBSDKAPPEventsWKWebViewMessagesProtocolKey
                       ];

      [controller addUserScript:[[WKUserScriptClass alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]];
    }
  }
  else {
    [FBSDKAppEventsUtility logAndNotify:@"You must call augmentHybridWKWebView with WebKit linked to your project and a WKWebView instance"];
  }
}
#endif

+ (void)setIsUnityInit:(BOOL)isUnityInit
{
  [FBSDKAppEvents singleton]->_isUnityInit = isUnityInit;
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+ (void)sendEventBindingsToUnity
{
  // Send event bindings to Unity only Unity is initialized
  if ([FBSDKAppEvents singleton]->_isUnityInit
      && [FBSDKAppEvents singleton]->_serverConfiguration
      && [NSJSONSerialization isValidJSONObject:[FBSDKAppEvents singleton]->_serverConfiguration.eventBindings]
      ) {
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[FBSDKAppEvents singleton]->_serverConfiguration.eventBindings ?: @""
                                                       options:0
                                                         error:nil];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    Class classFBUnityUtility = objc_lookUpClass(FBUnityUtilityClassName);
    SEL updateBindingSelector = NSSelectorFromString(FBUnityUtilityUpdateBindingsSelector);
    if ([classFBUnityUtility respondsToSelector:updateBindingSelector]) {
      [classFBUnityUtility performSelector:updateBindingSelector withObject:jsonString];
    }
  }
}
#pragma clang diagnostic pop

#pragma mark - Internal Methods

+ (void)logImplicitEvent:(NSString *)eventName
              valueToSum:(NSNumber *)valueToSum
              parameters:(NSDictionary *)parameters
             accessToken:(FBSDKAccessToken *)accessToken
{
  [[FBSDKAppEvents singleton] instanceLogEvent:eventName
                                    valueToSum:valueToSum
                                    parameters:parameters
                            isImplicitlyLogged:YES
                                   accessToken:accessToken];
}

+ (FBSDKAppEvents *)singleton
{
  static dispatch_once_t pred;
  static FBSDKAppEvents *shared = nil;

  dispatch_once(&pred, ^{
      shared = [[FBSDKAppEvents alloc] init];
    });
  return shared;
}

- (void)flushForReason:(FBSDKAppEventsFlushReason)flushReason
{
  // Always flush asynchronously, even on main thread, for two reasons:
  // - most consistent code path for all threads.
  // - allow locks being held by caller to be released prior to actual flushing work being done.
  @synchronized (self) {
    if (!_appEventsState) {
      return;
    }
    FBSDKAppEventsState *copy = [_appEventsState copy];
    _appEventsState = [[FBSDKAppEventsState alloc] initWithToken:copy.tokenString
                                                           appID:copy.appID];
    dispatch_async(dispatch_get_main_queue(), ^{
      [self flushOnMainQueue:copy forReason:flushReason];
    });
  }
}

#pragma mark - Private Methods
- (NSString *)appID
{
  return [FBSDKAppEvents loggingOverrideAppID] ?: [FBSDKSettings appID];
}

- (void)publishInstall
{
  NSString *appID = [self appID];
  if (appID.length == 0) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Missing [FBSDKAppEvents appID] for [FBSDKAppEvents publishInstall:]"];
    return;
  }
  NSString *lastAttributionPingString = [NSString stringWithFormat:@"com.facebook.sdk:lastAttributionPing%@", appID];
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  if ([defaults objectForKey:lastAttributionPingString]) {
    return;
  }
  [self fetchServerConfiguration:^{
    NSDictionary *params = [FBSDKAppEventsUtility activityParametersDictionaryForEvent:@"MOBILE_APP_INSTALL"
                                                                    implicitEventsOnly:NO
                                                             shouldAccessAdvertisingID:self->_serverConfiguration.isAdvertisingIDEnabled];
    NSString *path = [NSString stringWithFormat:@"%@/activities", appID];
    FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:path
                                                         parameters:params
                                                        tokenString:nil
                                                         HTTPMethod:@"POST"
                                                              flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError | FBSDKGraphRequestFlagDisableErrorRecovery];
    [request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
      if (!error) {
        [defaults setObject:[NSDate date] forKey:lastAttributionPingString];
        NSString *lastInstallResponseKey = [NSString stringWithFormat:@"com.facebook.sdk:lastInstallResponse%@", appID];
        [defaults setObject:result forKey:lastInstallResponseKey];
        [defaults synchronize];
      }
    }];
  }];
}

#if !TARGET_OS_TV
- (void)enableCodelessEvents {
  if (_serverConfiguration.isCodelessEventsEnabled) {
    if (!_eventBindingManager) {
      _eventBindingManager = [[FBSDKEventBindingManager alloc] init];
      [_eventBindingManager start];
    }

    if ([FBSDKInternalUtility isUnity]) {
      [FBSDKAppEvents sendEventBindingsToUnity];
    } else {
      [_eventBindingManager updateBindings:[FBSDKEventBindingManager
                                            parseArray:_serverConfiguration.eventBindings]];
    }
  }
}
#endif

// app events can use a server configuration up to 24 hours old to minimize network traffic.
- (void)fetchServerConfiguration:(void (^)(void))callback
{
  [FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *error) {
    self->_serverConfiguration = serverConfiguration;

    if (self->_serverConfiguration.implicitPurchaseLoggingEnabled) {
      [FBSDKPaymentObserver startObservingTransactions];
    } else {
      [FBSDKPaymentObserver stopObservingTransactions];
    }
#if !TARGET_OS_TV
    [self enableCodelessEvents];
#endif
    if (callback) {
      callback();
    }
  }];
}

- (void)instanceLogEvent:(NSString *)eventName
              valueToSum:(NSNumber *)valueToSum
              parameters:(NSDictionary *)parameters
      isImplicitlyLogged:(BOOL)isImplicitlyLogged
             accessToken:(FBSDKAccessToken *)accessToken
{
  if (isImplicitlyLogged && _serverConfiguration && !_serverConfiguration.isImplicitLoggingSupported) {
    return;
  }

  if (!isImplicitlyLogged && !_explicitEventsLoggedYet) {
    _explicitEventsLoggedYet = YES;
  }

  __block BOOL failed = NO;

  if (![FBSDKAppEventsUtility validateIdentifier:eventName]) {
    failed = YES;
  }

  // Make sure parameter dictionary is well formed.  Log and exit if not.
  [parameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
      if (![key isKindOfClass:[NSString class]]) {
        [FBSDKAppEventsUtility logAndNotify:[NSString stringWithFormat:@"The keys in the parameters must be NSStrings, '%@' is not.", key]];
        failed = YES;
      }
      if (![FBSDKAppEventsUtility validateIdentifier:key]) {
        failed = YES;
      }
      if (![obj isKindOfClass:[NSString class]] && ![obj isKindOfClass:[NSNumber class]]) {
        [FBSDKAppEventsUtility logAndNotify:[NSString stringWithFormat:@"The values in the parameters dictionary must be NSStrings or NSNumbers, '%@' is not.", obj]];
        failed = YES;
      }
    }
   ];

  if (failed) {
    return;
  }

  NSMutableDictionary *eventDictionary = [NSMutableDictionary dictionaryWithDictionary:parameters];
  eventDictionary[FBSDKAppEventParameterEventName] = eventName;
  if (!eventDictionary[FBSDKAppEventParameterLogTime]) {
    eventDictionary[FBSDKAppEventParameterLogTime] = @([FBSDKAppEventsUtility unixTimeNow]);
  }
  [FBSDKInternalUtility dictionary:eventDictionary setObject:valueToSum forKey:@"_valueToSum"];
  if (isImplicitlyLogged) {
    eventDictionary[FBSDKAppEventParameterImplicitlyLogged] = @"1";
  }

  NSString *currentViewControllerName;
  if ([NSThread isMainThread]) {
    // We only collect the view controller when on the main thread, as the behavior off
    // the main thread is unpredictable.  Besides, UI state for off-main-thread computations
    // isn't really relevant anyhow.
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController;
    if (vc) {
      currentViewControllerName = [[vc class] description];
    } else {
      currentViewControllerName = @"no_ui";
    }
  } else {
    currentViewControllerName = @"off_thread";
  }
  eventDictionary[@"_ui"] = currentViewControllerName;

  NSString *tokenString = [FBSDKAppEventsUtility tokenStringToUseFor:accessToken];
  NSString *appID = [self appID];

  @synchronized (self) {
    if (!_appEventsState) {
      _appEventsState = [[FBSDKAppEventsState alloc] initWithToken:tokenString appID:appID];
    } else if (![_appEventsState isCompatibleWithTokenString:tokenString appID:appID]) {
      if (self.flushBehavior == FBSDKAppEventsFlushBehaviorExplicitOnly) {
        [FBSDKAppEventsStateManager persistAppEventsData:_appEventsState];
      } else {
        [self flushForReason:FBSDKAppEventsFlushReasonSessionChange];
      }
      _appEventsState = [[FBSDKAppEventsState alloc] initWithToken:tokenString appID:appID];
    }

    [_appEventsState addEvent:eventDictionary isImplicit:isImplicitlyLogged];
    if (!isImplicitlyLogged) {
      [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
                         formatString:@"FBSDKAppEvents: Recording event @ %ld: %@",
       [FBSDKAppEventsUtility unixTimeNow],
       eventDictionary];
    }

    [self checkPersistedEvents];

    if (_appEventsState.events.count > NUM_LOG_EVENTS_TO_TRY_TO_FLUSH_AFTER &&
        self.flushBehavior != FBSDKAppEventsFlushBehaviorExplicitOnly) {
      [self flushForReason:FBSDKAppEventsFlushReasonEventThreshold];
    }
  }
}

// this fetches persisted event states.
// for those matching the currently tracked events, add it.
// otherwise, either flush (if not explicitonly behavior) or persist them back.
- (void)checkPersistedEvents
{
  NSArray *existingEventsStates = [FBSDKAppEventsStateManager retrievePersistedAppEventsStates];
  if (existingEventsStates.count == 0) {
    return;
  }
  FBSDKAppEventsState *matchingEventsPreviouslySaved = nil;
  // reduce lock time by creating a new FBSDKAppEventsState to collect matching persisted events.
  @synchronized(self) {
    if (_appEventsState) {
      matchingEventsPreviouslySaved = [[FBSDKAppEventsState alloc] initWithToken:_appEventsState.tokenString
                                                  appID:_appEventsState.appID];
    }
  }
  for (FBSDKAppEventsState *saved in existingEventsStates) {
    if ([saved isCompatibleWithAppEventsState:matchingEventsPreviouslySaved]) {
      [matchingEventsPreviouslySaved addEventsFromAppEventState:saved];
    } else {
      if (self.flushBehavior == FBSDKAppEventsFlushBehaviorExplicitOnly) {
        [FBSDKAppEventsStateManager persistAppEventsData:saved];
      } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          [self flushOnMainQueue:saved forReason:FBSDKAppEventsFlushReasonPersistedEvents];
        });
      }
    }
  }
  if (matchingEventsPreviouslySaved.events.count > 0) {
    @synchronized(self) {
      if ([_appEventsState isCompatibleWithAppEventsState:matchingEventsPreviouslySaved]) {
        [_appEventsState addEventsFromAppEventState:matchingEventsPreviouslySaved];
      }
    }
  }
}

- (void)flushOnMainQueue:(FBSDKAppEventsState *)appEventsState
               forReason:(FBSDKAppEventsFlushReason)reason
{

  if (appEventsState.events.count == 0) {
    return;
  }

  if (appEventsState.appID.length == 0) {
    [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors logEntry:@"Missing [FBSDKAppEvents appEventsState.appID] for [FBSDKAppEvents flushOnMainQueue:]"];
    return;
  }

  [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];

  [self fetchServerConfiguration:^(void) {
    NSString *receipt_data = [appEventsState extractReceiptData];
    NSString *encodedEvents = [appEventsState JSONStringForEvents:self->_serverConfiguration.implicitLoggingEnabled];
    if (!encodedEvents) {
      [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
                             logEntry:@"FBSDKAppEvents: Flushing skipped - no events after removing implicitly logged ones.\n"];
      return;
    }
    NSMutableDictionary *postParameters = [FBSDKAppEventsUtility
                                           activityParametersDictionaryForEvent:@"CUSTOM_APP_EVENTS"
                                           implicitEventsOnly:appEventsState.areAllEventsImplicit
                                           shouldAccessAdvertisingID:self->_serverConfiguration.advertisingIDEnabled];
    NSInteger length = receipt_data.length;
    if (length > 0) {
      postParameters[@"receipt_data"] = receipt_data;
    }

    postParameters[@"custom_events"] = encodedEvents;
    if (appEventsState.numSkipped > 0) {
      postParameters[@"num_skipped_events"] = [NSString stringWithFormat:@"%lu", (unsigned long)appEventsState.numSkipped];
    }
    if (self.pushNotificationsDeviceTokenString) {
      postParameters[FBSDKActivitesParameterPushDeviceToken] = self.pushNotificationsDeviceTokenString;
    }

    NSString *loggingEntry = nil;
    if ([FBSDKSettings.loggingBehaviors containsObject:FBSDKLoggingBehaviorAppEvents]) {
      NSData *prettyJSONData = [NSJSONSerialization dataWithJSONObject:appEventsState.events
                                                               options:NSJSONWritingPrettyPrinted
                                                                 error:NULL];
      NSString *prettyPrintedJsonEvents = [[NSString alloc] initWithData:prettyJSONData
                                                                encoding:NSUTF8StringEncoding];
      // Remove this param -- just an encoding of the events which we pretty print later.
      NSMutableDictionary *paramsForPrinting = [postParameters mutableCopy];
      [paramsForPrinting removeObjectForKey:@"custom_events_file"];

      loggingEntry = [NSString stringWithFormat:@"FBSDKAppEvents: Flushed @ %ld, %lu events due to '%@' - %@\nEvents: %@",
                      [FBSDKAppEventsUtility unixTimeNow],
                      (unsigned long)appEventsState.events.count,
                      [FBSDKAppEventsUtility flushReasonToString:reason],
                      paramsForPrinting,
                      prettyPrintedJsonEvents];
    }

    FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:[NSString stringWithFormat:@"%@/activities", appEventsState.appID]
                                                         parameters:postParameters
                                                        tokenString:appEventsState.tokenString
                                                         HTTPMethod:@"POST"
                                                              flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError | FBSDKGraphRequestFlagDisableErrorRecovery];

    [request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
      [self handleActivitiesPostCompletion:error
                              loggingEntry:loggingEntry
                            appEventsState:(FBSDKAppEventsState *)appEventsState];
    }];

  }];
}

- (void)handleActivitiesPostCompletion:(NSError *)error
                          loggingEntry:(NSString *)loggingEntry
                        appEventsState:(FBSDKAppEventsState *)appEventsState
{
  typedef NS_ENUM(NSUInteger, FBSDKAppEventsFlushResult) {
    FlushResultSuccess,
    FlushResultServerError,
    FlushResultNoConnectivity
  };

  [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];

  FBSDKAppEventsFlushResult flushResult = FlushResultSuccess;
  if (error) {
    NSInteger errorCode = [error.userInfo[FBSDKGraphRequestErrorHTTPStatusCodeKey] integerValue];

    // We interpret a 400 coming back from FBRequestConnection as a server error due to improper data being
    // sent down.  Otherwise we assume no connectivity, or another condition where we could treat it as no connectivity.
    // Adding 404 as having wrong/missing appID results in 404 and that is not a connectivity issue
    flushResult = (errorCode == 400 || errorCode == 404) ? FlushResultServerError : FlushResultNoConnectivity;
  }

  if (flushResult == FlushResultServerError) {
    // Only log events that developer can do something with (i.e., if parameters are incorrect).
    //  as opposed to cases where the token is bad.
    if ([error.userInfo[FBSDKGraphRequestErrorKey] unsignedIntegerValue] == FBSDKGraphRequestErrorOther) {
      NSString *message = [NSString stringWithFormat:@"Failed to send AppEvents: %@", error];
      [FBSDKAppEventsUtility logAndNotify:message allowLogAsDeveloperError:!appEventsState.areAllEventsImplicit];
    }
  } else if (flushResult == FlushResultNoConnectivity) {
    @synchronized(self) {
      if ([appEventsState isCompatibleWithAppEventsState:_appEventsState]) {
        [_appEventsState addEventsFromAppEventState:appEventsState];
      } else {
        // flush failed due to connectivity. Persist to be tried again later.
        [FBSDKAppEventsStateManager persistAppEventsData:appEventsState];
      }
    }
  }

  NSString *resultString = @"<unknown>";
  switch (flushResult) {
    case FlushResultSuccess:
      resultString = @"Success";
      break;

    case FlushResultNoConnectivity:
      resultString = @"No Connectivity";
      break;

    case FlushResultServerError:
      resultString = [NSString stringWithFormat:@"Server Error - %@", error.description];
      break;
  }

  [FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorAppEvents
                     formatString:@"%@\nFlush Result : %@", loggingEntry, resultString];
}

- (void)flushTimerFired:(id)arg
{
  [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];
  if (self.flushBehavior != FBSDKAppEventsFlushBehaviorExplicitOnly && !self.disableTimer) {
    [self flushForReason:FBSDKAppEventsFlushReasonTimer];
  }
}

- (void)applicationDidBecomeActive
{
  [FBSDKAppEventsUtility ensureOnMainThread:NSStringFromSelector(_cmd) className:NSStringFromClass([self class])];

  [self checkPersistedEvents];

  // Restore time spent data, indicating that we're not being called from "activateApp".
  [FBSDKTimeSpentData restore:NO];
}

- (void)applicationMovingFromActiveStateOrTerminating
{
  // When moving from active state, we don't have time to wait for the result of a flush, so
  // just persist events to storage, and we'll process them at the next activation.
  FBSDKAppEventsState *copy = nil;
  @synchronized (self) {
    copy = [_appEventsState copy];
    _appEventsState = nil;
  }
  if (copy) {
    [FBSDKAppEventsStateManager persistAppEventsData:copy];
  }
  [FBSDKTimeSpentData suspend];
}

#pragma mark - Custom Audience

+ (FBSDKGraphRequest *)requestForCustomAudienceThirdPartyIDWithAccessToken:(FBSDKAccessToken *)accessToken
{
  accessToken = accessToken ?: [FBSDKAccessToken currentAccessToken];
  // Rules for how we use the attribution ID / advertiser ID for an 'custom_audience_third_party_id' Graph API request
  // 1) if the OS tells us that the user has Limited Ad Tracking, then just don't send, and return a nil in the token.
  // 2) if the app has set 'limitEventAndDataUsage', this effectively implies that app-initiated ad targeting shouldn't happen,
  //    so use that data here to return nil as well.
  // 3) if we have a user session token, then no need to send attribution ID / advertiser ID back as the udid parameter
  // 4) otherwise, send back the udid parameter.

  if ([FBSDKAppEventsUtility advertisingTrackingStatus] == FBSDKAdvertisingTrackingDisallowed || [FBSDKSettings limitEventAndDataUsage]) {
    return nil;
  }

  NSString *tokenString = [FBSDKAppEventsUtility tokenStringToUseFor:accessToken];
  NSString *udid = nil;
  if (!accessToken) {
    // We don't have a logged in user, so we need some form of udid representation.  Prefer advertiser ID if
    // available, and back off to attribution ID if not.  Note that this function only makes sense to be
    // called in the context of advertising.
    udid = [FBSDKAppEventsUtility advertiserID];
    if (!udid) {
      udid = [FBSDKAppEventsUtility attributionID];
    }

    if (!udid) {
      // No udid, and no user token.  No point in making the request.
      return nil;
    }
  }

  NSDictionary *parameters = nil;
  if (udid) {
    parameters = @{ @"udid" : udid };
  }

  NSString *graphPath = [NSString stringWithFormat:@"%@/custom_audience_third_party_id", [[self singleton] appID]];
  FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:graphPath
                                                       parameters:parameters
                                                      tokenString:tokenString
                                                       HTTPMethod:nil
                                                            flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError | FBSDKGraphRequestFlagDisableErrorRecovery];

  return request;
}

@end

redpajama_set_name: RedPajamaGithub


text:
BA Cityflyer E-190 G-LCYO Gemini Jets GJBAW1247 March 2016
Posted on March 25, 2016 March 25, 2016 by Jon Champs
The first of the larger Embraer E-jets Gemini produced was the pretty ropey KLM whose engines were not the best and the model was generally not well assembled. That must be around three years ago. There have been very few of any type made since. I can only think of an AA E195 (I never purchased it as E-195's are slightly longer by 6.25mm at 1:400 scale and the model was't), and I think a recent-ish Virgin Australia, which doesn't fit my collecting criteria at all.
Herpa made a really nice if expensive 1:400 E-170, G-LCYF that the E-190 joined in BA Cityflyer's fleet when delivered – in 2011. It's taken Gemini a long time to produce an aircraft type BA has had in service since 2009. And still no Lufthansa version though they're all being moved to Austrian to replace their Fokker's), or Flybe (who still have 5).
It has to be pointed out that while a wholly owned subsidiary of British Airways, Cityflyer Express Ltd has its own call sign, "Flyer", IATA code, CJ and ICAO code, CFE. It's main base of operations is London City (LCY) and it effectively services the East End and Docklands/Canary Wharf financial districts. BA operates 2 A318's from LCY to JFK, but not under the Cityflyer brand, which is mostly near-Europe regional and UK domestic services.
London City Airport (LCY), Home of BA Cityflyer and the A318's. Special steep approach training for pilots is required along with aircraft certified for the purpose.
In the summer of 2016 Cityflyer is starting to operate from Stansted, partly down to space and slot restrictions at LCY, but also to cope with increased fuel and luggage requirements – LCY is very limited in terms of runway length.This allows them to service up-market holiday destinations like Mykonos in Greece and Malaga/Puerto Banus in Spain. With 13 E-190's, 6 E-170's, along with 2 Saab 2000's it uses on lease from Eastern Airways, it's a fairly substantial specialist regional airline with a unique market.
Only today, 23rd March 2016 it was announced that E-190's would be wet-leased at weekends to Aer Lingus now owned by parent IAG. This gives better utilization of the E-190's which have little to do at weekends, and relieves Aer Lingus Dublin-UK routes, now at capacity.
While the ERJ-170-100STD's are 76 seaters, the ERJ-190-100SR's are 98, and only when you see them side by side do you realize fully how big the E-190 is. Having flown on both I find the E-Jets extraordinarily plasticky inside, though they are quiet, and the slim line seats are comfortable.
The interior on BA's E-190's has a moveable divider so that when flying domestic, all 98 seats are economy. The final position of the divider is usually only decided just minutes before departure on European flights, so that those paying business fares, who still get the same economy seat, are separated from the rest of the passengers to have their expensive in flight meals served. The seats are 18.3″ wide with a 34″ pitch – better than economy on a BA 744! Can't have those City fat-cat's complaining can we?
Generally it's OK. A small thing, is that the structural ridge under the rear of the tail section (which correctly, has an aerial at the front end of it), just doesn't stick out as it does on the model at the far end, it's flush with the main body.
A bigger thing is a defect in the mould that has left a slight, but discernible, dip in the roofline in the centre. The only other model I've had with this before was an Apollo 744F Asiana cargo converted from passenger use.
The dip in the roof line is clearly visible here, right above the B in British
While having gone to some trouble to have the aerial at the rear underneath in, none of the other three are present.
There is also something about the Gemini production number that suggests this has been sitting around for some time waiting to be produced and nobody updated the file before production. As a result, it lacks details like the TFTS shield, the lettering YO at the top of the tail and the CYO on the nose gear doors, all of which are present on the real thing and have been since a service in October 2014. She is in effect, in her delivery livery.
Kink in the paint line on one side is very noticeable
Other than those omissions (or not depending on your point of view, Gemini don't specify which year it's meant to be), this is so much better made than the KLM one, and totally, vastly, superior to the latest batch of A320's Gemini have produced.
Even so the rear blue-white transition line is poor on the starboard side especially, where it has too-visible a kink upwards, that just shouldn't be there. The rest of the detail is otherwise very good.
Excellent wings, really good. Detail and paint application are first class. Slot in wings are well fitted.
Unusually, the hole for the stand on this mode (which fits well) is rear of centre, an observation only!
Landing gear is all round excellent, its ideally sized tyres on wheels work well, they all move, good detail, well made.
3)Engines
The two GE CF34-10E5's look excellent side on, but the silver rims again! Why is it that they cannot find a paint that wants to adhere correctly at a fine enough particle size, to look good? The rims look flakey, they look like the silver was applied before the blue gloss underneath was dry and any model maker knows that that's a no-no! In general, silver paint doesn't like sitting on gloss paint that is dry, it just doesn't bond well.
Flaky silver rims and leeched blue paint – a direct result of poor bonding
The engines also have a silver over-cowling at the top of the exhaust that's missing. The silver exhaust paint is too bright and the rear of the exhaust cones aren't silver. You might say this is being picky, but they've managed this type of detail on other models when it suits them, so why not here? Herpa's much smaller E170 engines are far superior.
Sadly it doesn't quite pass the eyeball test, you can see blue leeching through the silver, especially on the rims. Average.
4)Nose detail
The blue-white line is very shaky, and that's being generous. It's an eyeball test fail as well which is even more annoying. Cockpit windows are all pretty good though.
The dip in the roof really notices at this angle
5)Tail detail
The vertical is fine, the horizontals are stuck in well but they are tilted too high, they should be much flatter. It's not a terrible fault on such a small model, but it's just not ideal. The port stabiliser has paint missing at the end of the rear edge.
No issues, perfect.
As far as I'm concerned this is a current model and it's never been advertised as anything other than that.
-7 for various paint issues, the blue kink, uneven nose paint, wobbly lines
-6 for missing detail, the TFTS x2, tail lettering x2, nose gear door x2 (both of these should have been there anyway, the much smaller Herpa E170 has the nose door lettering for example).
-1 for the under-bar shape
-4 for the engine paint fails
-2 for the dip in the mould roof
80% is a marginal pass. It's not really Manufacturer of the Year standards is it?
Herpa's smaller, E-170 may have been more expensive new, but it's a much better model in almost every way than the larger Gemini E-190
In all honesty, the much smaller 1:400 Herpa E170 is a better model, though now very rare, I can't even remember seeing one on eBay in the last 12 months.Even the Delta and Air France Régional versions of that have vanished, and they were around a lot longer, having been released at the same time.
The engines on that are barely a third of the size of the E-190 and yet they're far better finished.
So how to conclude? It's a must have model this one, it's been on BA collectors wish lists for an age. That's why nobody will complain. And yet while superficially it looks fine, it's actually not outstanding in any way. It's OK, it's average, which, as we keep seeing, is the best anyone seems to want to make these days. The word "excellence" doesn't seem to come into it.
I so wish this business wasn't dominated by just two major manufacturers, one minor, and four brands. It needs more competition and it needs it now; only that will drive up quality.
I'll be back on April 4th after a family celebration and a week in San Francisco, I've got hold of a model of possibly one of the most interesting – and long serving – aircraft still plying the skies! Have a great Easter and if you're on vacation, enjoy!
Please go to the 1400Reviews Facebook page in the link below and like us there! LIKE 1400Reviews on Facebook & follow us on twitter
Tags: 1:400, 1:400 scale, aircraft, airlines, airport, aviation, BA, British Airways, Cityflyer, collection, collector, dioramas, E-170, E-190, E-jet, Embraer, ERJ-190, G-LCYF, G-LCYO, Gemini jets, GJBAW1247, Herpa, review, reviews, RLSICategories: 1400 reviews, 1400reviews, 1:400, 1:400 scale, aircraft, airline routes, airlines, airports, British Airways, British Airways Cityflyer, Embraer, ERJ-190

redpajama_set_name: RedPajamaCommonCrawl


LAS VEGAS (AP) – Autumn de Forest's signature includes a heart hovering over the second "U" of her first name.
Considering that she turned 15 a few weeks ago, that's not much of a surprise.
The surprise is where that distinctively girlish signature appears: on paintings that, collectively, have sold for millions of dollars.
But maybe it's not so surprising. After all, Autumn has been a working artist for most of her young life.
The first public showing of her work took place in 2009 at Boulder City's annual Art in the Park, where she won an award a year after she first picked up a brush, at age 5.
Since then, Autumn's paintings – and Autumn herself – have traveled the globe.
Last year, she visited Rome to accept the International Giuseppe Sciacca Award for Painting and Art _ and presented a painting, titled "Resurrection," to Pope Francis.
This year, the Butler Institute of American Art in Youngstown, Ohio, extended Autumn's solo exhibit from two months to almost four because of its popularity.
Now, she's heading to Miami Art Week for Red Dot, a juried show featuring the works of more than 500 contemporary artists.
Last weekend, Autumn stayed home – for her first Las Vegas exhibition at the Gallery of Music & Art in the Forum Shops at Caesars, where her work will be a permanent feature at the gallery, director Barry Jacobson said.
Alongside some of Autumn's paintings is a video monitor featuring footage of her working on canvases taller than she is.
You can still see that little girl in the enthusiastic, articulate – more accurately, downright chatty – teen of today.
Hovering over a table placed in the back of the gallery – which has been expanded to include studio space – Autumn wields bottles of brightly colored acrylic paint, then picks up a metal rod to push fluorescent red, pink and yellow streaks across a sheet of canvas, conjuring a striated sunset.
That's "one of the great benefits of living in Las Vegas: some absolutely gorgeous sunsets and sunrises," she says.
The gallery is "really my first home for my works here in Las Vegas," and having a studio means she can present workshops similar to the ones she's led, from New York to California, as a member of the President's Committee on the Arts and the Humanities.
"It's such an incredible opportunity," Autumn says of the committee's Turnaround Arts program, which counts cellist Yo-Yo Ma, actress Reese Witherspoon and other "older but influential people" among its members.
The kids in the program "don't look upon those people as a peer; I'm their age," she says.
And when she helps them create self-portraits she uses a technique she calls "Face Values," with photographs projected onto blank canvases.
"It's something very personal to them," Autumn says.
"She is a great peer role model – embodying the ideals of the confidence, joy and success that students can achieve through the arts," Fletcher said in an email.
That's what Autumn has done since the day her dad, Doug, was staining some wood and Autumn picked up a paintbrush. Her dad said it looked like a Rothko.
Autumn had no idea who Mark Rothko was – then.
Now, the renowned abstract expressionist is one of her favorite artists.
From Jackson Pollock's drip-paint abstracts to Andy Warhol's pop art portraits, Autumn's influences emerge from her canvases.
When she painted a bouffant-coiffed Barbie doll in the style of Warhol's Marilyn Monroe, Autumn thought, "`If he can do this with Marilyn Monroe, I can do this with Barbie,"' her mother, Katherine, says.
Louis Zona, Butler Institute executive director, says that as with any younger artist, Autumn is searching for her own style.
After Autumn's first effort (the one that reminded her father of Rothko), "I did more and more," she says.
Of course, both Doug and Katherine de Forest were predisposed to foster their only child's creativity. He's a musician and composer; she's a former actor and model.
After Autumn made her Art in the Park debut, the word got out "and somehow it got to the Discovery Channel," he says, followed by NBC's "Today Show," PBS, the syndicated "Inside Edition" and more, all by age 9.
Autumn estimates she has painted almost 2,000 canvases. Katherine estimates that translates to "probably $7 million worth" of paintings. The money goes into a trust.
Although Autumn wasn't aware of it when she first picked up a paintbrush, she's not the first member of the de Forest family with an artistic bent. Her great-great-uncle Robert Weeks de Forest served as the president of New York's Metropolitan Museum of Art from 1913 to 1931. And her great-great-uncle Lockwood de Forest (1850-1932) was a member of the Hudson River School, according to Doug, whose sister and aunt also are artists.
And while "a lot of my friends know I love to paint," she doesn't tell them that she travels internationally in connection with painting.
"It's almost like looking into a mirror," she says.


It was OK. We got to the final and it's an improvement on our racing in our heat. But we still need to move on massively if we're going to do better in the next round. We had a much better start than we usually do, but we need to get a better rhythm in the middle of the race, which is something we did quite well in the heat. There is no one here in that race that we've not beaten. We just need to keep our heads in. The crews who are going to medal in two day's time are the ones who can turn things around, who can get to the start line on Thursday with the confidence and belief they can do it, and we really need to draw that into ourselves.


SOME BRAND MASH-UPS ARE CONFOUNDING FROM THE OUTSET (CYNTHIA ROWLEY AND PAMPERS, UGG AND TEVA, TO NAME JUST TWO), WHILE OTHERS SOUND INCONGRUOUS WHEN THEY'RE ANNOUNCED BUT, WHEN FULLY EXECUTED, FIT TOGETHER SURPRISINGLY WELL. IN THIS LATTER CATEGORY IS THE COLLABORATION BETWEEN PAR-IS-BASED FASHION DESIGNER RICK OWENS AND BIRKENSTOCK, THE GERMAN MAKER OF STRAPPY, CONTOURED-FOOTBED SANDALS, THAT WILL BE STOMPING INTO LOS ANGELES LATER THIS MONTH.
THE COLLABORATION IS PART OF BIRKENSTOCK'S BOX PROGRAM, A GLOBE-TROTTING, TEMPORARY EXPERIENTIAL RETAIL SPACE THAT CONSISTS OF TWO STACKED METAL SHIPPING CONTAINERS WITH AN INTERIOR DESIGNED BY THE PARTNER BRAND AND SHOWCASING LIMITED-EDITION PIECES. WHAT'S NOTABLE ABOUT THE OWENS COLLABORATION — IN ADDITION TO THE FACT THAT THE POP-UP WILL BE IN FRONT OF HIS LA BREA AVENUE BOUTIQUE FROM APRIL 17 TO 21 — IS THAT ALL OF THE PREVIOUS PERIPATETIC POP-UPS HAVE BEEN PARTNERSHIPS WITH MULTI-BRAND RETAILERS INCLUDING BERLIN'S ANDREAS MURKUDIS, MILAN'S 10 CORSO COMO AND BARNEYS NEW YORK.
SPECIFICALLY, THERE ARE THREE CLASSIC BIRKENSTOCK SILHOUETTES — THE TWO-STRAP ARIZONA SANDAL; THE SINGLE-STRAP MADRID; AND THE SLIP-ON BOSTON CLOG — THAT OWENS HAS SERVED UP IN NOVEL FABRICATIONS THAT INCLUDE HAIRY GRAY OR BLACK COWHIDE, DIRT-BROWN FELT, TAUPE-COLORED SUEDE AND BLACK FULL-GRAIN LEATHER. OTHER TWEAKS ARE MORE SUBTLE; SANDAL STRAPS HAVE BEEN ELONGATED SO FAR PAST THE BUCKLE THAT THEY COME CLOSE TO DANGLING ON THE FLOOR, EACH ONE PUNCTUATED WITH NEARLY FOUR TIMES AS MANY BUCKLE HOLES AS YOU'D FIND ON STANDARD BIRKS. THE COLLABORATION ALSO INCLUDES OWENS' RIFF ON BIRKENSTOCK'S SOCKS, WHICH WILL ALSO BE STOCKED IN THE BOX. (OWENS HAS ALSO DESIGNED A SEPARATE READY-TO-WEAR CAPSULE COLLECTION THAT'S ONLY BEING SOLD IN THE BOX SPACE.) FOOTWEAR IN THE BIRKENSTOCK X RICK OWENS COLLECTION WILL RETAIL FROM $350 TO $525 WITH HOSIERY RANGING FROM $94.95 TO$149.95. IN ADVANCE OF THE COLLABORATION'S RELEASE (THE FOOTWEAR IS CURRENTLY AVAILABLE FOR PRE-ORDER AT WWW.RICKOWENS.EU), WE HOPPED ON THE PHONE WITH FASHION'S DARK PRINCE FOR A TRANSATLANTIC CONVERSATION THAT TOUCHED ON HIS INSPIRATION, NUDIST CAMPS AND MUSING ON WHETHER GERMAN ARTIST JOSEPH BEUYS EVER WORE BIRKENSTOCKS. HERE ARE SOME EXCERPTS FROM THAT CONVERSATION.
WHEN DID BIRKENSTOCK FIRST CROSS YOUR RADAR?
I REMEMBER [THEM] AS A KID GROWING UP IN PORTERVILLE [CALIF.]. I REMEMBER BIRKENSTOCK HAVING A COUNTERCULTURE ALLURE THEN. THE FACT THAT THEY WEREN'T FRIVOLOUSLY PRETTY MADE THEM THE OPPOSITE OF FASHION, WHICH WAS KIND OF A LITTLE BIT MORE SERIOUS AND STUDIOUS. AND I DON'T THINK THAT COOL COUNTERCULTURE THING HAS REALLY CHANGED.
WHO WAS WEARING BIRKENSTOCKS AT THAT TIME?
IN THE '70S, WHEN I WAS IN HIGH SCHOOL, I FEEL LIKE IT WAS THE SCRUFFIER, SURFER/SKIER KIDS WHO WORE THEM. [BIRKENSTOCKS] ALWAYS HAD A LITTLE BIT OF AN OUTSIDER APPEAL. ALSO, THE KIND OF PEOPLE THAT WORE THEM SEEMED TO BE A LITTLE MORE ACTIVE AND OUTDOORSY SO THAT HAD TREMENDOUS APPEAL TOO. …THE OTHER THING I THINK ABOUT WHEN I THINK OF BIRKENSTOCK IS THOSE 1930S SUN-WORSHIPING NUDIST CAMPS THAT I KIND OF ASSOCIATE WITH GERMANY IN THE '30S, AND THAT'S ONE OF THE FIRST THINGS THAT COMES TO MY MIND. [BIRKENSTOCKS] WOULD HAVE BEEN THE PERFECT THING FOR ONE OF THOSE NUDIST CAMPS.
I DO. I WEAR THEM AT THE BEACH. I DON'T WEAR THEM IN THE CITY. I'M ONE OF THOSE PEOPLE WHO DOESN'T THINK THAT SANDALS REALLY BELONG IN THE CITY. I'M KIND OF A TRADITIONALIST THAT WAY. AND I WAS JUST THINKING ABOUT THIS THIS MORNING. I HAVE THIS WEIRD THING WHERE I DON'T PARTICULARLY LIKE SEEING MEN'S FEET.
AH, SO THAT EXPLAINS WHY ALL THE MODELS IN THE BIRKENSTOCK X RICK OWENS LOOK BOOK ARE WEARING SOCKS. DID YOU DESIGN THOSE?
I TOOK THEIR [SOCK DESIGNS] AND ALTERED THEM, MADE THEM LONGER. BECAUSE ONE OF THE THINGS I DO, WHEN I LOOK BACK ON WHAT I MIGHT REPRESENT [IN THE COLLABORATION], A LOT OF THE BASIC STUFF I'VE DONE, IT'S ALWAYS GOING A LITTLE BIT TOO FAR. THE T-SHIRTS ARE A LITTLE BIT LONG. THE SHOES ARE LITTLE BIT TOO BIG. IT'S THE VERY KIND OF LITERAL, ALMOST INNOCENT, INTERPRETATION OF THINKING OUTSIDE THE BOX. IT'S A SUBTLE WAY OF SUGGESTING THAT THE RULES THAT WE'VE BEEN TOLD DON'T NECESSARILY [APPLY].
AND THAT'S KIND OF WHAT I WAS DOING WITH BIRKENSTOCK. I THOUGHT, 'WELL, YOU KNOW, I COULD PUT SEQUINS ON THEM. I COULD MAKE THEM IN CORDOVAN LEATHER OR ALLIGATOR OR SOMETHING,' BUT I THOUGHT IT WOULD BE MORE PROFOUND TO ACTUALLY ALTER THEIR SHAPE. SO I EXTENDED THE STRAPS BECAUSE WHEN I FIRST STARTED DOING CLOTHES, MY WOMEN'S DAY DRESSES HAD TRAINS AND THINGS WERE TRAILING, AND THINGS WERE FALLING OFF. AND SO THAT'S KIND OF WHAT I DID WITH [THE] BIRKENSTOCKS. I MADE THE STRAPS A LITTLE TOO LONG AND WHEN THINGS ARE A LITTLE BIT TOO MUCH TO ME, THERE'S A SUBTLE NOTE OF EXTRAVAGANCE AND IMPRACTICALITY.… SO TO BE ABLE TO DO THAT TO SOMETHING THAT'S VERY PRACTICAL LIKE A BIRKENSTOCK WAS WHAT MADE OUR COLLABORATION MAKE SENSE.
ONE OF THE MATERIALS YOU USED IS LONG-HAIRED COWHIDE, WHICH SEEMS SORT OF IMPRACTICAL, BUT HOW ELSE DID YOU ADD THAT SENSE OF EXTRAVAGANCE?
I ALSO ADDED MORE HOLES FOR THE BUCKLE THAN WERE NECESSARY BECAUSE THOSE HOLES ADD A NOTE OF CONFECTION. IN A VERY ABSTRACT WAY, IT'S ON ITS WAY TO LACE, WHICH IS A CONFECTION, AND IT WAS JUST ENOUGH OF A DECORATIVE ELEMENT FOR ME.
WAS THERE ANY SPECIFIC INSPIRATION BEYOND THAT?
NO, THAT WAS PRETTY MUCH IT. I JUST THOUGHT, 'HOW CAN I GIVE THE RICK OWENS TOUCH TO SOMETHING SO SOLID AND WITH SUCH A SENSE OF HONOR?' IT SEEMS LIKE THE BRAND HAS MAINTAINED ITS INTEGRITY AND STOOD THE TEST OF TIME BY NOT LABORING. …WHO WOULDN'T WANT TO BE A BRAND LIKE THAT?
IN ADDITION TO THE FOOTWEAR AND SOCK COLLABORATION, YOU DESIGNED THE INTERIOR OF THE ACTUAL BOX SPACE — THE TWO SHIPPING CONTAINERS THAT WILL BE STACKED OUTSIDE YOUR LA BREA AVENUE STORE. WHAT INSPIRED THE LOOK CUSTOMERS WILL FIND INSIDE?
WHEN I THINK OF GERMANY, I [THINK OF] JOSEPH BEUYS AND I WONDERED IF JOSEPH BEUYS EVER WORE BIRKENSTOCKS. YOU THINK HE WOULD — THAT WOULD HAVE BEEN GREAT. I USE GRAY FELT IN MY COLLECTIONS ALL THE TIME BECAUSE OF BEUYS, AND IT'S WHY I USED FELT AS ONE OF THE FABRIC OPTIONS IN THE BIRKENSTOCKS [IN THE COLLECTION]. SO I THOUGHT THE STORE COULD BE A LITTLE BIT OF A JOSEPH BEUYS TEMPLE. THE INTERIOR [ALSO] INCLUDES SOME OF THE FURNITURE THAT I'VE BEEN DOING, UPHOLSTERED IN GRAY FELT, TO CREATE A KIND OF NICE, COCOON[-LIKE] ENVIRONMENT. MY OTHER THOUGHT WHEN I LOOKED AT THAT SPACE WAS ONE OF MY ALL-TIME FAVORITE PLACES IN THE WORLD — LE CORBUSIER'S SUMMER CABIN IN THE SOUTH OF FRANCE. IT'S A SMALL, ONE-ROOM CABIN, BUT THE WAY IT WAS CONSTRUCTED WITH THE WOOD INTERIOR MAKES IT THE ULTIMATE LE CORBUSIER WOMB. SO WHEN I WAS THINKING ABOUT THE BOX, I ENVISIONED A CROSS BETWEEN THAT CABIN AND A JOSEPH BEUYS TEMPLE.


text:
In Love with KPOP
Hazel.Lora.Denz
Spit it out!
You are currently browsing the category archive for the 'Se7en' category.
Se7en to Promote "Girls" in 3 Major U.S. Cities
March 19, 2009 in Se7en | by aitsukame | Leave a comment
Se7en will begin full-scale promotional activities in three major cities: New York, Atlanta, and Washington DC.
YG Entertainment said, "Se7en will spend time promoting 'Girls.' First he'll start with cities in the east side of the United States."
"Girls" was released on March 11 (Korea time). The music video ranked at #5 on Myspace, and has a 5-star rating (the highest) on iTunes by users.
Source: Newsen
Credit: seoulfull.wordpress.com
Please take out only with credit and do not add any credits.
Se7en's 'Girls' MV
Se7en's official MV is out!
Se7en Girls Music Video Ft. Lil Kim
Se7en debuts in the USA with 'Girls'
Se7en (real name Choi Dong-wook) finally makes his American debut!
Se7en has been promoting his English songs through preview parties namely at Hiro Ballroom in New York City and other parties across the US and Canada. He officially makes his debut in the USA on 10th March, 2009 with the single "Girls".
The single comes with a music video which is released simultaneously in the States, Korea and Japan. The debut song "Girls" was produced by well known producer Dark Child. Lil Kim is also featured in this song.
vid cr: FaBoLoUsXxGiRlXx
Source: Osen + K-popped!
Se7en's 'Girls' MV Teaser
March 4, 2009 in Se7en | by aitsukame | Leave a comment
[youtub=http://www.youtube.com/watch?v=t-DR4s6HhrY]
vid cr: iluvJaejoongix2
Se7en is Going Back to Korea
February 27, 2009 in Se7en | by aitsukame | Leave a comment
Se7en is going back to Korea … this fall, this according to an interview with Yonhap news and YG Entertainment CEO / Former Seo Taiji member Yang Hyun Suk.
Before he returns to Korea, he'll finish up his activities in America and Japan. Se7en plans to release his debut song "Girls" on iTunes on March 10th. Then two to three months down the line they're planning to release a second single. Se7en will then go to Japan in the summer to have some activities in the Japanese market. Finally returning back to Korea in the Fall, after more than 2 years in America.
YG CEO Yang Hyun Suk said this in the interview:
This isn't about album sales, more so about signaling Se7en's debut into the American market. We don't except our first single to enter the Billboard Charts or even receive a lot of sales, but that doesn't mean we haven't succeeded. We worked with famous musicians and producers such as Lil' Kim and DarkChild, that in itself is half-success. I had meetings with some industry contacts in America, such as officials at Interscope Records. Through these meetings I was able to have Lil Kim's participation. Another prominent US musician will be featured in Se7en's second single.
We never anticipated Se7en's debut to take such a long time with so many delays. During the process, he was working hard learning English and constantly recording music. At the same time, we were still researching the American market for Asian artists. It's very difficult in America because there isn't any Musical Ranking Type shows like back in Korea. Even TRL on MTV is gone now, so that makes it difficult. Constant Radio play and Music Videos are most crucial in America, and MTV won't play just a random foreign singer with a different look, musical style, and someone who can't speak English properly. To have Se7en's MV play on TV and have his music play on local radio stations across the nation is the key.
Another key is to change the focus / perception from being recognized as solely Korean / Asian to simply Artist. A person who has succeeded in this is actress Kim Yun-Jin. She's recognized as her character on Lost and not solely as an Asian.
I said to Se7en that although he is a star back in Korea, he's a relative nobody over here. Pouring money into it doesn't guarantee that you'll succeed. You must work hard and make music that fits the taste of the American market. You must also have fluent English and present yourself in a way that'll attract an audience. Although money doesn't guarantee success, it does help. We need to receive capital and have deals in place with major record agencies. We would need them to help shoulder the marketing and promotional costs.
source: allkpop
M.net Super 100 Flower Boys
February 26, 2009 in Big Bang, Dong Bang Shin Ki, F.T. Island, Other Artists, Rain/Bi, Se7en, SHINee, SS501, Super Junior | by aitsukame | 1 comment
1. Lee Minho
2. Kang Dong Won
3. Kim Bum
4. Yoongwoong Jaejoong (DBSK)
5. Matsumoto Jun (Arashi)
6. Kim Hyunjoong (SS501)
7. Nick Khun
8. Jung Il Woo
9. Oguri Shun
10. Jo In Sung
11. Moon Mason
12. Joo Ji Hoon
13. Vic Zhou
14. Taemin (SHINee)
15. Lee Yong Dae
16. Micky Yoochun (DBSK)
17. Akanishi Jin (Kat-tun)
18. Kim Jae Wook
19. Yamamini coopera Tomohisa/Yamapi (NewS)
20. Jang Geun Suk
21. Minho (SHINee)
22. Heechul (Super Junior)
23. Boyd Holbrook (model)
24. Kim Yo-Han
25. Lee Jun Ki
26. Ji Seung Jun (Shoot Dori)
27. Andrea Goldberg (Model)
28. Kibum (Super Junior)
29. Ji Hyun Woo
30. Yoo Seung Ho
31. Choikang Changmin (DBSK)
32. Tamaki Hiroshi
33. Yoo Ah In
34. Hongki (FT Island)
35. Mokomichi Hayami
36. TOP (Big Bang)
37. Hyunbin
38. Lee Seung Gi
39. Gaspard Ulliel
40. Kamenashi Kazuya (KAT-TUN)
41. Sungmin (Super Junior)
42. Hwang Kidong
43. Teppei Koike (WAT)
44. Lee Dong Wook
45. Mun Sungmin
46. Ricky Kaka
47. Se7en
48. Jung Eui Chul
49. Tsumabuki Satoshi
50. U-know Yunho (DBSK)
51. G-Dragon (Big Bang)
52. Zack Efron
53. Lee Dong Gun
54. Miura Haruma
55. Im Joo Hwan
56. Nicholas Holt
57. Cheon Jeong Myeong
58. Kim Hyungjoon (SS501)
59. Park Tae Hwan
60. Ryan Curry
61. Shin Min Cheol
62. Mitchell Scott Hewer
63. Kyuhyun (Super Junior)
64. Mingus Lucien Reedus
65. Kim Hyesung
66. Donghae (Super Junior)
67. Kim Dong Wook
68. Joe Cheng
69. Fredrik Stenman
70. Joseph McManners
71. Park Hae Jin
72. Siwon (Super Junior)
73. Kim Jung Hoon
74. Matsuda Shota
75. Kim Joon
76. Nu Min Woo (Trax)
77. Baek Ji hoon
78. Chase Crawford
79. Baek Seung Hyun
80. Onew (SHINee)
81. Evan Yoo
82. Toma Ikuta
83. Hong Jong Hyun
84. Jonghun (FT Island)
85. John G Weir
86. Song Joong Ki
87. Eita
88. Kim Si Hoo
90. Lee Wan
91. Sung Je (Supernova)
92. Lee Hyun Jin
93. Matt Anderson (Volleyball player)
94. Jinwoon (2AM)
95. Jiro Wang (Fahrenheit)
96. Chris (Battle)
97. Ben Barnes
98. Kim Min Seok
99. Taegoon
100. Lee Hae Woo
cr: tarobun@soompi.com + sapphirepearls
**The bolded ones are those whom I love XD
Se7en Worldwide Offical Site Now Open
Se7en's official site (www.se7enworldwide.com) is now opened as of 25th February.
His American debut single 'Girls' teaser video will be released on the 4th, full MV on 1oth March American time.
The digital single 'Girls' will be released on iTunes from 10th March as well as other sites like Rhapsody, Amazon and Napster.
source: sookyeong
YG Speaks Up About Se7en's American Debut, "We didn't know the debut will take so long"
YG Entertainment Yang Hyun Seok spoke up about singer Se7en's (25) American debut in an interview recently.
In the interview, Yang said, "We didn't know that his debut will take this long and late. Se7en has been practising on his English and singing all this while non-stop."
He added, "Se7en's American debut song 'Girlz' will be revealed on iTunes and he will release a 2nd single 2-3 months after that. After which, He will be promoting in Japan during July-August and then return back to Korea in October."
"The digital single 'Girlz' is produced by famous producer in American and features rapper Lil Kim. Lil Kim will also appear about 40% of time in the MV. We are not hoping to see the song get into Billboard top 100. We think that to have such great people work on this single is already half of the success."
About Se7en's late debut in America, "We didn't know it will take this long and late. All this while, Se7en has only been practising on his English and singing. We are debuting Se7en 1 year later because we are being careful and constantly analyzing the American market because until now there hasn't been a successful Asian singer in America."
"The American market, do not have the weekly music broadcast programs like in Korea, hence MV and radio play is very important here. Would you want to make an MV that shows an imperfect language, image and music style that is influenced by other music and then all rejected by your target market? We want Se7en's music and MV to be an inspiration when it is broadcasted."
We see many Asian actors making their way into the American market like Kim Yoon Jin, but many a times their success depends on the character and role they play in the movie/show and they are often chosen because of their Asian origins.
"But for singers, it is the fine line of victory or defeat. That's why we have Lil Kim to support the acceptance of song 'Girlz'. Se7en's 2nd single will also have the particiation of a famous American artiste."
"I keep telling Se7en, 'You are not a Korean star here, you are purely a new singer'. America is not a country made of money. You got to enter with the type of music the market wants and with the right language-grasp. You also need to strategies by working with the local music firms and talents."
Se7en to Open Official Worldwide Homepage for American Debut
Singer Se7en will have his official homepage for his American debut up on 24th February.
YG Entertainment announced, " Se7en Worldwide (www.se7enworldwide.com) will be opened on 24th. This homepage will update on Se7en's American debut, his songs, videos and also photos."
This will be Se7en's first worldwide homepage apart from his own MySpace page. There will also be an event for the opening of the homepage where fans can get to meet Se7en.
Se7en's new song 'Girlz' will be revealed on 10th March and the MV teaser on 4th March.
Not Again! Se7en's American Debut Postponed
Singer Se7en's American debut date has yet again been postponed.
Initially, the plan was to have Se7en debut on Valentines' Day which is 14th February with the song 'Girlz' but it was postponed to 4th March on the reason that more preparation work is needed.
And now, YG Entertainment is saying that there is still more preparation work to be done and had set the date to be on 10th March for the song to be official revealed.
YG Entertainment said in a phone interview on 12th February, "We have decided to go with revealing the song on 10th March. The music video teaser will be revealed on 4th March."
This is Se7en's American debut 2 years in the making.
There are plans for Se7en to promote in Korea for certain period of time after his American debut. It will be great news for Se7en fans since it has been a long time since Se7en has promoted in Korea.
SHINee Juliette Remix @ Inki
KPOP World
Batang KPOP Lover
F.T. Island
Mod's Post
Rain/Bi
Maraming Salamat
WRAP-UP THE KPOP LOVE


All soloists, the musicians of DA PACEM master early music repertoire played on period instruments and contemporary creation using modern instruments, or instruments based on new technologies, with the same ease.
From late Renaissance to the baroque era, their historical requirement is built around thematic projects. They imagine a dramaturgy specific to each concert, in a wide variety of timbres and atmospheres. The italian styled organ, especially built for them by the organ builder Quentin Blumenroeder, takes part in a rich, unified continuo group to support the voice.
The soprano Raphaële Kennedy and the composer Pierre-Adrien Charpy, founders of the ensemble in 1998, also imposed it as a laboratory of contemporary musical research and dialogue with popular and erudit music belonging to oral traditions.
Neither interbreeding, nor mixing, nor cross-over, their approach favors real encounter and confrontation, with rigour and sensitivity.
The pieces of Tomás Luis de Victoria's Officium Hebdomadae Sanctae were inserted into a complex and very long set of services. Rather than a liturgical reenactment or a re-contextualization, we propose the quintessence of this musical repertoire, with the nine Tenebrae Lessons and the eighteen Responsories of Holy Week, for a total of twenty seven pieces unanimously regarded as one of the greatest masterpieces of sacred music.
Le doux parfum des temps à venir explores the sands of memory and imagination, from the confidences of a mother – in the evening of her life – to her daughter. This story in the feminine, written by a man, questions many faces of truth, as elusive and rich as a fragrance. The show stages this transmission of relentless pursuit of oneself through the strange bifurcations of life, its secrets and its colors, thanks to the encounter of sounds and words which are all reflections of a fleeting reality. Artists on stage question the presence of a single reality, past and present meet in the transmission of an intense desire : to be and to reach one's full potential.
Just like music, fragrance is immaterial. Just like music, it speaks to the dark side of our being. It has the ability to reveal what is not yet illuminated or to conjure what was forgotten. […] This cantata will be a nocturnal one. And a feminine one. It expresses the sincerity of a mother's true love of her daughter, illuminated with the dazzling images of the poetic text. It takes place « in the sight of stars which simply twinkle ». And by word of mouth, once the seal of lie is broken, the maternal confession will release the daughter from fear and hate, and will lead her to her woman fragrance.
Happiness, to love and be loved : this is the quest of the one who does everything he can to sigh, to please, to have the advantage, to win the heart with some victorious appeal, to love tenderly, to cherish, sometimes in ardour, sometimes in sweetness, always in constancy. In these second half of Eighteenth-century airs sérieux, brunetes or petits airs tendres and chansons pour danser, feelings rush : anger, shame, pity, sorrow and trouble echo torment, disorder, confusion. While grievances fill the air in extreme sadness and slowness, the active forces exceed reason that we call for help.
The women who feature in the poetry of Purcell's songs are all so many contrasted images. We can find in Orpheus Britannicus and Harmonia sacra – whose extracts are the object of this program – the absent beloved woman, the scornful or cruel one, the eternally in love one, the later to become Queen, the goddess, the Virgin. With his incomparable genius Purcell pays homage to all of these images of women, all equally captivating.
We were charmed by the perfect match between the soprano and Purcell's music. The musicians delighted soul and imagination, while the soloist hovered above them in an almost way. It was a unique, magical moment.
The soprano gave her many-sided, flexible voice to all these women […]. She evolves in clear arabesques, lives and modulates her texts with perfect diction.
In addition to displaying the beauty and natural elasticity of a well-placed voice, this young woman, […] brings a beautiful consistency to each of these works, achieving a rich and brilliant palette of feelings. Her task is rendered all the more easy by a solid continuo quartet who glorify Purcell's scores.
It is a voice with contrasting inflexions, alternately sensual, cheerful, celestial, moving, which is well served by the instrumentalists.
At the turning point between the 16th and 17th centuries, the notion of music in the image of the harmony of the spheres was progressively abandoned in favour of a musical art which was a vector of the expression of the passions of the human soul. Of all these passions, by far the greatest centre of concern to the poets was love; and as it would not have been seemly to boast of a happy love, amorous disarray was deconstructed in all its forms.
Who can resist the pleasure of exploring the universe of this wonderful composer? He was a true middleman between different musical styles and periods, who achieved a staggering synthesis of the polyphonic, numerical and rhetorical traditions of his predecessors with a very personal poetry, by building musical structures of hitherto unknown richness, all embellished with great tenderness, taking care to make his music accessible to everyone, from the specialist to the layman. It is not surprising that Bach took him as his model!
A perfect musical alchemy. […] The performers have not saved their many talents. Raphaële Kennedy's diaphanous and aerial timbre knows how to be embodied in vibrating accents. […] This soprano has a deep sense of declamation that works marvelously in this music that is constantly based on the text.
[…] soprano Raphaële Kennedy makes herself an exact accomplice of Buxtehude's piety. […] [She] knows how to stimulate the power of words from within, in both Latin and German motets. She adds virtuosity to fair expressiveness, not being a conqueror sure of her effects but being anxious to touch rather than to please. Thus appears the more ardent portrait of this outstanding creator […].