 import ReactiveCocoa
 import Result
 
+public enum CurrentOrUpdate<UpdateInfo> {
+    case current
+    case update(UpdateInfo)
+}
+
+public enum CurrentOrUpdateOrAction<UpdateInfo, ActionInfo> {
+    case current
+    case update(UpdateInfo)
+    case action(ActionInfo)
+}
+
 public final class ViewModelProperty<Value, UpdateInfo, ActionInfo> {
-    public let updateProducer: SignalProducer<(Value, UpdateInfo), NoError>
-    public fileprivate(set) lazy var noInfoUpdateProducer: SignalProducer<Value, NoError> = self.updateProducer.map { (value, _) in value }
-    fileprivate let updateObserver: Signal<(Value, UpdateInfo), NoError>.Observer
+    public let updateSignal: Signal<(Value, UpdateInfo), NoError>
+    private let updateObserver: Signal<(Value, UpdateInfo), NoError>.Observer
     
     public let actionSignal: Signal<(Value, ActionInfo), NoError>
-    public fileprivate(set) lazy var noInfoActionSignal: Signal<Value, NoError> = self.actionSignal.map { (value, _) in value }
-    fileprivate let actionObserver: Signal<(Value, ActionInfo), NoError>.Observer
+    private let actionObserver: Signal<(Value, ActionInfo), NoError>.Observer
     
-    public fileprivate(set) lazy var mergedProducer: SignalProducer<Value, NoError> = { [unowned self] () -> SignalProducer<Value, NoError> in
+    // MARK: - Derived signals
+    
+    public private(set) lazy var updateProducer: SignalProducer<(Value, CurrentOrUpdate<UpdateInfo>), NoError> = { [unowned self] in
+        return SignalProducer { observer, producerDisposable in
+            observer.sendNext((self._value, .current))
+            
+            producerDisposable += self.updateSignal.observeNext { (value, updateInfo) in
+                observer.sendNext((value, .update(updateInfo)))
+            }
+        }
+    }()
+    
+    public private(set) lazy var allChangeProducer: SignalProducer<(Value, CurrentOrUpdateOrAction<UpdateInfo, ActionInfo>), NoError> = { [unowned self] in
+        return SignalProducer { observer, producerDisposable in
+            observer.sendNext((self._value, .current))
+            
+            producerDisposable += self.updateSignal.observeNext { (value, updateInfo) in
+                observer.sendNext((value, .update(updateInfo)))
+            }
+            
+            producerDisposable += self.actionSignal.observeNext { (value, actionInfo) in
+                observer.sendNext((value, .action(actionInfo)))
+            }
+        }
+    }()
+    
+    public private(set) lazy var noInfoUpdateSignal: Signal<Value, NoError> = self.updateSignal.map { (value, _) in value }
+    public private(set) lazy var noInfoActionSignal: Signal<Value, NoError> = self.actionSignal.map { (value, _) in value }
+    public private(set) lazy var noInfoUpdateProducer: SignalProducer<Value, NoError> = self.updateProducer.map { (value, _) in value }
+    public private(set) lazy var noInfoAllChangeProducer: SignalProducer<Value, NoError> = self.allChangeProducer.map { (value, _) in value }
+    
+    // MARK: -
+    
+    public private(set) lazy var changingProducer: SignalProducer<Value, NoError> = { [unowned self] () -> SignalProducer<Value, NoError> in
         return SignalProducer<Value, NoError> { observer, producerDisposable in
             self.updateProducer.startWithSignal { signal, cancelDisposable in
                 producerDisposable += cancelDisposable

}

public extension ViewModelProperty where UpdateInfo: NoInfoType {
    convenience public init(_ initialValue: Value) {
        self.init(initialValue, info: UpdateInfo())
    }
    
    public func setValueByUpdate(_ newValue: Value) -> Value {
        return setValueByUpdate(newValue, info: UpdateInfo())
    }

        }
    }()
    
    private let lock: NSRecursiveLock
    private var _value: Value
    
    public var value: Value {
        get {
