 (ns hellhound.component
-  (:require [clojure.spec.alpha :as s]
-            [clojure.spec.gen.alpha :as gen])
+  (:require [clojure.spec.alpha     :as s]
+            [clojure.spec.gen.alpha :as gen]
+            [manifold.stream        :as stream]
+            [hellhound.core :as core])
   (:import (clojure.lang PersistentArrayMap)))
 
 
 ;; Protocols
 (defprotocol IComponent
   "This protocol defines a very basic component for hellhound system."
+  (initialize [component]
+    "Returns the initialized component.")
+
   (start! [component context]
     "Starts the component.")
 

                        :fn #(= (::name (:ret %))
                                (::name (:this (:args %)))))))

(s/def ::stop-fn (s/fspec :args (s/cat :this map? :context map?)
                          :ret map?
                          :fn #(= (::name (:ret %))
                                  (::name (:this (:args %))))))

(s/def ::depends-on (s/coll-of keyword? :kind vector? :distinct true))
(s/def ::component (s/keys :req [::name ::start-fn ::stop-fn]
                           :opt [::depends-on]))


(extend-type PersistentArrayMap
  IComponent
  (initialize [component]
    (let [default-io-buffer-size (core/get-config :components :io-buffer-size)
          default-stream-fn #(stream/stream default-io-buffer-size)
          input-stream-fn   (get component
                                 :input-stream-fn
                                 default-stream-fn)
          output-stream-fn  (get component
                                 :output-stream-fn
                                 default-stream-fn)]
      (assoc component
             :input (input-stram-fn)
             :outpu (output-stream-fn))))


  (start! [this context]
    (let [start-fn (::start-fn this)]
      (assoc (start-fn this context)
