 (defonce app-state
   (atom {:selected [:details]
          :rsvp-search {:name ""
-                       :results nil}
+                       :results nil
+                       :party {}}
+         :party {}
+         :selection {:party nil
+                     :guests nil}
          :response {:contact nil
                     :food-preferences ""
-                    :infos nil
+                    :infos {}
                     :sent false}}))
 
+(defn search []
+  (om/ref-cursor (:rsvp-search (om/root-cursor app-state))))
+
+(defn selection []
+  (om/ref-cursor (get-in (om/root-cursor app-state) [:selection])))
+
 (defn response []
-  (om/ref-cursor (:response (om/root-cursor app-state))))
+  (om/ref-cursor (get-in (om/root-cursor app-state) [:response])))
 
 (defonce Response (.extend (.-Object parse/Parse) "Response"))
 (defonce Info (.extend (.-Object parse/Parse) "Info"))

              (map (fn [[key text]]
                     [:li (if (= selected [key]) {:class "selected"} {})
                      [:a {:href "#"
                           :onClick #(do (om/update! rsvp-search :results nil)
                                         (om/update! rsvp-search :guests-in-party nil)
                                         (om/update! rsvp-search :party nil)
                                         (om/update! selected 0 key))}
                       text]])
                   (partition 2 [:details       "Details"

         [:button {:type "submit"}
          "Find RSVP"]]]))))

(defn send-rsvps! [{:keys [party guests] :as selection} {:keys [contact food-preferences infos sent] :as response}]
  (go (try (let [[result response-or-error] (<! (parse/save Response {:party (let [p (Party.)]
                                                                               (set! (.-id p)
                                                                                     (get-in party [:id]))
                                                                               p)
                                                                      :contact contact
                                                                      :foodPreferences food-preferences}))]
             (if (= :success result)
               (doseq [[id {:keys [corrected-name attending]}] infos]
                 (let [[result info-or-error] (<! (parse/save Info {:response response-or-error
                                                                    :guest (let [g (Guest.)]
                                                                             (set! (.-id g)
                                                                                   id)
                                                                             g)
                                                                    :correctedName corrected-name
                                                                    :attending attending}))]
                   (when-not (= result :success)
                     (js/console.error "Error! Error! " info-or-error)
                     (throw info-or-error))))
               (throw response-or-error)))
           [:success]
           (catch :default e
             [:error e]))))

(defn rsvp-card-view [{:keys [party guests] :as selection} owner]
  (reify
    om/IRender
    (render [_]
      (let [{:keys [contact food-preferences infos] :as response} (om/observe owner (response))]
        (when (nil? contact)
          (om/update! response :contact (:contact party)))
        
        (html
         [:div
          [:main
           [:h1 "Selection"]
           [:code (with-out-str (cljs.pprint/pprint selection))]
           [:h1 "Response"]
           [:code (with-out-str (cljs.pprint/pprint response))]]
          [:main
           [:h2 "RSVP"]
           [:form {:id "rsvpsubmit"
                   :onSubmit (fn [e]
                               (.preventDefault e)
                               (go (let [[result data] (<! (send-rsvps! selection response))]
                                     (condp = result
                                       :success (om/update! response :sent true)
                                       :failure (js/console.error "Error sending response to Parse:" data)))))}
            [:section {:class "guests"}
             (map-indexed
              (fn [idx {id :id, original-name :name :as info}]
                [:div
                 [:input {:type "text"
                          :class "guestname"
                          :value (or (get-in infos [id :corrected-name]) original-name)
                          :ref (str id "name")
                          :onChange #(om/update! response [:infos id :corrected-name] (.-value (om/get-node owner (str id "name"))))}]
                 [:fieldset
                  [:div
                   (let [radio-name (str "guest" idx "rsvp")]
                     (map (fn [[label for-str val]]
                            (let [input-id (str "guest" idx for-str)]
                              [:div
                               [:input (cond-> {:type "radio"
                                                :id input-id
                                                :name radio-name
                                                :onChange #(om/update! response [:infos id :attending] val)}
                                         (= val (get-in infos [id :attending]))
                                         (assoc :checked true))]
                               [:label {:for input-id}
                                label]]))
                          (partition 3 ["Will attend"   "yes" true
                                        "Sends regrets" "no" false])))]]])
              guests)
             [:p {:class "small"}
              "(If we've gotten anyone's name wrong, we apologize! Please correct it here so that we can stop embarrassing ourselves.)"]]
            [:section {:class "addendums"}
             [:label {:for "foodpref", :class "small"}
              "We are planning on serving a buffet style meal that will be suitable for both meat eaters and vegetarians. Do you have any dietary restrictions or allergies that we should be aware of?"]
             [:textarea {:name "foodpref"
                         :ref "food-preferences"
                         :value food-preferences
                         :onChange #(om/update! response :food-preferences (.-value (om/get-node owner "food-preferences")))}]

             [:label {:for "contact" :class "small"}
              "If we need to contact you with any last-minute information, is this a good email address to use?"]
             [:input {:type "text"
                      :ref "contact"
                      :value contact
                      :onChange #(om/update! response :contact (.-value (om/get-node owner "contact")))}]

             [:button {:type "submit"} "RSVP"]]]]])))))

(defn rsvp-multiple-results-view [{:keys [name results] :as data} owner]
  (reify
