     }
   }
 
-  func next(value: T) {
+  func next(value: ValueType) {
     dispatch_async(queue) { [weak self] in
       if value != self?.value {
         self?.value = value

//

import Foundation

struct ObservableSubject<T>: Equatable {
  let guid = NSUUID().UUIDString
  let observeOn: dispatch_queue_t
  let observable: (T) -> ()
}

func ==<T>(lhs: ObservableSubject<T>, rhs: ObservableSubject<T>) -> Bool {
  return lhs.guid == rhs.guid
}

class Observable<T where T: Equatable> {

  private let queue = dispatch_queue_create("nl.tomasharkema.Observable", DISPATCH_QUEUE_SERIAL)

  private var value: T? = nil {
    didSet {
      notifiy()
    }
  }
  
  private var subjects = [ObservableSubject<T>]()

  private func notifiy() {
    dispatch_async(queue) { [weak self] in
      if let value = self?.value, subjects = self?.subjects {
        for subject in subjects {
          dispatch_async(subject.observeOn) {
            subject.observable(value)
          }
        }
      } else {
        print("Notifying without value?!")
      }
    }
  }

  func subscribe(observeOn: dispatch_queue_t = dispatch_get_main_queue(), subject: (T) -> ()) -> ObservableSubject<T> {
    var subscription: ObservableSubject<T>!
    dispatch_sync(queue) { [weak self] in
      subscription = ObservableSubject(observeOn: observeOn, observable: subject)
      self?.subjects.append(subscription)
    }
    if let value = value {
      dispatch_async(observeOn) {
        subject(value)
      }
    }
    return subscription
  }

  func unsubscribe(subject: ObservableSubject<T>) {
    dispatch_async(queue) { [weak self] in
      if let index = self?.subjects.indexOf(subject) {
        self?.subjects.removeAtIndex(index)


  init() {}

  init(initialValue: ValueType) {
    value = initialValue
  }
}

// MARK: Once Trigger

extension Observable {
  func once(observeOn: dispatch_queue_t = dispatch_get_main_queue(), subject: (ValueType) -> ()) -> ObservableSubject<ValueType> {
    var subscription: ObservableSubject<ValueType>!
    dispatch_sync(queue) { [weak self] in
      subscription = ObservableSubject(observeOn: observeOn, observable: subject, once: true)
      self?.subjects.append(subscription)
    }

    return subscription
  }
}

// MARK: Monad 🤓

extension Observable {
  func map<NewValueType>(transform: ValueType -> NewValueType) -> (mapSubscription: ObservableSubject<ValueType>, newObservable: Observable<NewValueType>) {
    let newObservable = Observable<NewValueType>()

    let subscription = subscribe {
      newObservable.next(transform($0))
    }

    return (subscription, newObservable)
  }

  func mapOnce<NewValueType>(transform: ValueType -> NewValueType) -> (mapSubscription: ObservableSubject<ValueType>, newPromise: Promise<NewValueType, NoError>) {
    let promise = PromiseSource<NewValueType, NoError>()

    let subscription = once {
      promise.resolve(transform($0))
    }

    return (subscription, promise.promise)
  }
}
