//
//  UIRefreshControl+YSRACCommandSupport.m
//  ReactiveObjC
//
//  Created by Dave Lee on 2013-10-17.
//  Copyright (c) 2013 GitHub, Inc. All rights reserved.
//

#import "UIRefreshControl+YSRACCommandSupport.h"
#import "YSRACEXTKeyPathCoding.h"
#import "YSRACCommand.h"
#import "YSRACCompoundDisposable.h"
#import "YSRACDisposable.h"
#import "YSRACSignal.h"
#import "YSRACSignal+Operations.h"
#import "UIControl+YSRACSignalSupport.h"
#import <objc/runtime.h>

static void *UIRefreshControlYSRACCommandKey = &UIRefreshControlYSRACCommandKey;
static void *UIRefreshControlDisposableKey = &UIRefreshControlDisposableKey;

@implementation UIRefreshControl (YSRACCommandSupport)

- (YSRACCommand *)ysrac_command {
	return objc_getAssociatedObject(self, UIRefreshControlYSRACCommandKey);
}

- (void)setRac_command:(YSRACCommand *)command {
	objc_setAssociatedObject(self, UIRefreshControlYSRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

	// Dispose of any active command associations.
	[objc_getAssociatedObject(self, UIRefreshControlDisposableKey) dispose];

	if (command == nil) return;

	// Like YSRAC(self, enabled) = command.enabled; but with access to disposable.
	YSRACDisposable *enabledDisposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self];

	YSRACDisposable *executionDisposable = [[[[[self
		ysrac_signalForControlEvents:UIControlEventValueChanged]
		map:^(UIRefreshControl *x) {
			return [[[command
				execute:x]
				catchTo:[YSRACSignal empty]]
				then:^{
					return [YSRACSignal return:x];
				}];
		}]
		concat]
		deliverOnMainThread]
		subscribeNext:^(UIRefreshControl *x) {
			[x endRefreshing];
		}];

	YSRACDisposable *commandDisposable = [YSRACCompoundDisposable compoundDisposableWithDisposables:@[ enabledDisposable, executionDisposable ]];
	objc_setAssociatedObject(self, UIRefreshControlDisposableKey, commandDisposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
