//
//  NSUserDefaults+YSRACSupport.m
//  ReactiveObjC
//
//  Created by Matt Diephouse on 12/19/13.
//  Copyright (c) 2013 GitHub, Inc. All rights reserved.
//

#import "NSUserDefaults+YSRACSupport.h"
#import "YSRACEXTScope.h"
#import "NSNotificationCenter+YSRACSupport.h"
#import "NSObject+YSRACDeallocating.h"
#import "YSRACChannel.h"
#import "YSRACScheduler.h"
#import "YSRACSignal+Operations.h"

@implementation NSUserDefaults (YSRACSupport)

- (YSRACChannelTerminal *)ysrac_channelTerminalForKey:(NSString *)key {
	NSParameterAssert(key != nil);

	YSRACChannel *channel = [YSRACChannel new];
	
	YSRACScheduler *scheduler = [YSRACScheduler scheduler];
	__block BOOL ignoreNextValue = NO;
	
	@weakify(self);
	[[[[[[[NSNotificationCenter.defaultCenter
		ysrac_addObserverForName:NSUserDefaultsDidChangeNotification object:self]
		map:^(id _) {
			@strongify(self);
			return [self objectForKey:key];
		}]
		startWith:[self objectForKey:key]]
		// Don't send values that were set on the other side of the terminal.
		filter:^ BOOL (id _) {
			if (YSRACScheduler.currentScheduler == scheduler && ignoreNextValue) {
				ignoreNextValue = NO;
				return NO;
			}
			return YES;
		}]
		distinctUntilChanged]
		takeUntil:self.ysrac_willDeallocSignal]
		subscribe:channel.leadingTerminal];
	
	[[channel.leadingTerminal
		deliverOn:scheduler]
		subscribeNext:^(id value) {
			@strongify(self);
			ignoreNextValue = YES;
			[self setObject:value forKey:key];
		}];
	
	return channel.followingTerminal;
}

@end
