         :data-success-text "Started..."
         :type "submit"}])]))
 
-(defn overview [project-data controls-ch]
-  [:div.project-settings-block
-   [:h2 "How to configure " [:span (vcs-url/project-name (get-in project-data [:project :vcs_url]))]]
-   [:ul.overview-options
-    [:li.overview-item
-     [:h4 "Option 1"]
-     [:p
-      "Do nothing! Circle infers many settings automatically. Works great for Ruby, Python, NodeJS, Java and Clojure. However, if it needs tweaks or doesn't work, see below."]]
-    [:li.overview-item
-     [:h4 "Option 2"]
-     [:p
-      "Override inferred settings and add new test commands "
-      [:a {:href "#setup"} "through the web UI"]
-      ". This works great for prototyping changes."]]
-    [:li.overview-item
-     [:h4 "Option 3"]
-     [:p
-      "Override all settings via a "
-      [:a {:href "/docs/configuration"} "circle.yml file"]
-      " in your repo. Very powerful."]]]])
-
-(defn mini-parallelism-faq [project-data controls-ch]
+(defn overview [project-data owner]
+  (reify
+    om/IRender
+    (render [_]
+      (html
+       [:div.project-settings-block
+        [:h2 "How to configure " (vcs-url/project-name (get-in project-data [:project :vcs_url]))]
+        [:ul.overview-options
+         [:li.overview-item
+          [:h4 "Option 1"]
+          [:p
+           "Do nothing! Circle infers many settings automatically. Works great for Ruby, Python, NodeJS, Java and Clojure. However, if it needs tweaks or doesn't work, see below."]]
+         [:li.overview-item
+          [:h4 "Option 2"]
+          [:p
+           "Override inferred settings and add new test commands "
+           [:a {:href "#setup"} "through the web UI"]
+           ". This works great for prototyping changes."]]
+         [:li.overview-item
+          [:h4 "Option 3"]
+          [:p
+           "Override all settings via a "
+           [:a {:href "/docs/configuration"} "circle.yml file"]
+           " in your repo. Very powerful."]]]]))))
+
+(defn mini-parallelism-faq [project-data]
   [:div.mini-faq
    [:div.mini-faq-item
     [:h3 "What are containers?"]

    (when show-fixed-failed?
      (fixed-failed-input project controls-ch :hipchat_notify_prefs))]])

(defn chatrooms [project-data controls-ch]
  (let [project (:project project-data)
        project-id (project-model/id project)]
    [:div
     [:h2 "Chatroom setup for" (vcs-url/project-name (:vcs_url project))]
     [:div.chat-rooms
      (for [chat-spec [{:service "Hipchat"
                        :icon "chat-i-hip"
                        :doc (list [:p "To get your API token, create a \"notification\" token via the "
                                    [:a {:href "https://hipchat.com/admin/api"} "HipChat site"] "."]
                                   [:label ;; hipchat is a special flower
                                    {:for "hipchat-notify"}
                                    [:input#hipchat-notify
                                     {:type "checkbox"
                                      :checked (:hipchat_notify project)
                                      :on-change #(utils/toggle-input controls-ch (conj state/project-path :hipchat_notify) %)}]
                                    [:span "Show popups"]])
                        :inputs [{:field :hipchat_room :placeholder "Room"}
                                 {:field :hipchat_api_token :placeholder "API"}]
                        :show-fixed-failed? true}

                       {:service "Campfire"
                        :icon "chat-i-camp"
                        :doc [:p "To get your API token, visit your company Campfire, then click \"My info\". Note that if you use your personal API token, campfire won't show the notifications to you!"]
                        :inputs [{:field :campfire_room :placeholder "Room"}
                                 {:field :campfire_subdomain :placeholder "Subdomain"}
                                 {:field :campfire_token :placeholder "API"}]
                        :show-fixed-failed? true}

                       {:service "Flowdock"
                        :icon "chat-i-flow"
                        :doc [:p "To get your API token, visit your Flowdock, then click the \"Settings\" icon on the left. On the settings tab, click \"Team Inbox\""]
                        :inputs [{:field :flowdock_api_token :placeholder "API"}]
                        :show-fixed-failed? false}

                       {:service "IRC"
                        :icon "chat-i-flow"
                        :doc nil
                        :inputs [{:field :irc_server :placeholder "Hostname"}
                                 {:field :irc_channel :placeholder "Channel"}
                                 {:field :irc_keyword :placeholder "Private Keyword"}
                                 {:field :irc_username :placeholder "Username"}
                                 {:field :irc_password :placeholder "Password (optional)"}]
                        :show-fixed-failed? true}

                       {:service "Slack"
                        :icon "chat-i-slack"
                        :doc [:p "To get your Webhook URL, visit Slack's "
                              [:a {:href "https://my.slack.com/services/new/circleci"}
                               "CircleCI Integration"]
                              " page, choose a default channel, and click the green \"Add CircleCI Integration\" button at the bottom of the page."]
                        :inputs [{:field :slack_webhook_url :placeholder "Webhook URL"}]
                        :show-fixed-failed? true}

                       {:service "Hall"
                        :icon "chat-i-hall"
                        :doc [:p "To get your Room / Group API token, go to "
                              [:strong "Settings > Integrations > CircleCI"]
                              " from within your Hall Group."]
                        :inputs [{:field :hall_room_api_token :placeholder "API"}]
                        :show-fixed-failed? true}]]
        (chatroom-item project controls-ch chat-spec))]
     [:div.chat-room-save
      (forms/stateful-button
       [:input
        {:data-success-text "Saved",
         :data-loading-text "Saving",
         :value "Save notification hooks",
         :type "submit",
         :on-click #(do (put! controls-ch [:saved-notification-hooks {:project-id project-id}]))}])]]))

(defn webhooks [project-data controls-ch]
  [:div
   [:h2 "Webhooks for " (vcs-url/project-name (get-in project-data [:project :vcs_url]))]
   [:div.doc
    [:p
     "Circle also support webhooks, which run at the end of a build. They can be configured in your "
     [:a {:href "https://circleci.com/docs/configuration#notify" :target "_blank"}
      "circle.yml file"] "."]]])

(defn ssh-keys [project-data controls-ch]
  (let [project (:project project-data)
        project-id (project-model/id project)
        {:keys [hostname public-key private-key]
         :or {hostname "" public-key "" private-key ""}} (:new-ssh-key project-data)]
    [:div.sshkeys-page
     [:h2 "SSH keys for " (vcs-url/project-name (:vcs_url project))]
     [:div.sshkeys-inner
      [:p "Add keys to the build VMs that you need to deploy to your machines. If the hostname field is blank, the key will be used for all hosts."]
      [:form
       [:input#hostname {:required true, :type "text" :value hostname
                         :on-change #(utils/edit-input controls-ch (conj state/project-data-path :new-ssh-key :hostname) %)}]
       [:label {:placeholder "Hostname"}]
       [:input#publicKey {:required true, :type "text" :value public-key
                          :on-change #(utils/edit-input controls-ch (conj state/project-data-path :new-ssh-key :public-key) %)}]
       [:label {:placeholder "Public Key"}]
       [:textarea#privateKey {:required true :value private-key
                              :on-change #(utils/edit-input controls-ch (conj state/project-data-path :new-ssh-key :private-key) %)}]
       [:label {:placeholder "Private Key"}]
       (forms/stateful-button
        [:input#submit.btn
         {:data-failed-text "Failed",
          :data-success-text "Saved",
          :data-loading-text "Saving..",
          :value "Submit",
          :type "submit"
          :on-click #(do (put! controls-ch [:saved-ssh-key {:project-id project-id
                                                            :ssh-key {:hostname hostname
                                                                      :public_key public-key
                                                                      :private_key private-key}}])
                         false)}])]
      (when-let [ssh-keys (seq (:ssh_keys project))]
        [:table
         [:thead [:tr [:th "Hostname"] [:th "Fingerprint"] [:th]]]
         [:tbody
          (for [{:keys [hostname fingerprint]} ssh-keys]
            [:tr
             [:td hostname]
             [:td fingerprint]
             [:td [:a {:title "Remove this Key?",
                       :on-click #(put! controls-ch [:deleted-ssh-key {:project-id project-id
                                                                       :fingerprint fingerprint}])}
                   [:i.fa.fa-times-circle]
                   [:span " Remove"]]]])]])]]))

(defn github-user [project-data controls-ch]
  [:div "Wait for "
   [:a {:href "https://github.com/circleci/circle/pull/2259"}
    "#2259"]
   " to merge."])

(defn api-tokens [project-data controls-ch opts]
  (let [project (:project project-data)
        project-id (project-model/id project)
        {:keys [scope label]
         :or {scope "status" label ""}} (:new-api-token project-data)]
    [:div.circle-api-page
     [:h2 "API tokens for " (vcs-url/project-name (:vcs_url project))]
     [:div.circle-api-page-inner
      [:p "Create and revoke project-specific API tokens to access this project's details using ourAPI. First choose a scope "
       ;; XXX popovers
       [:i.fa.fa-question-circle {:data-bind "popover"}]
       " and then create a label."]
      [:form
       [:div.styled-select
        [:select {:name "scope" :value scope
                  :on-change #(utils/edit-input controls-ch (conj state/project-data-path :new-api-token :scope) %)}
         [:option {:value "status"} "Status"]
         [:option {:value "all"} "All"]]
        [:i.fa.fa-chevron-down]]
       [:input
        {:required true, :type "text" :value label
         :on-change #(utils/edit-input controls-ch (conj state/project-data-path :new-api-token :label) %)}]
       [:label {:placeholder "Token label"}]
       (forms/stateful-button
        [:input
         {:data-failed-text "Failed",
          :data-success-text "Created",
          :data-loading-text "Creating...",
          :on-click #(do (put! controls-ch [:saved-project-api-token {:project-id project-id
                                                                      :api-token {:scope scope
                                                                                  :label label}}])
                         false)
          :value "Create token",
          :type "submit"}])]
      (when-let [tokens (seq (:tokens project-data))]
        [:table
         [:thead
          [:th "Scope"]
          [:th "Label"]
          [:th "Token"]
          [:th "Created"]
          [:th]]
         [:tbody
          (for [{:keys [scope label token time]} tokens]
            [:tr
             [:td scope]
             [:td label]
             [:td [:span.code token]]
             [:td time]
             [:td
              [:a.slideBtn
               {:title "Remove this Key?",
                :on-click #(put! controls-ch [:deleted-project-api-token {:project-id project-id
                                                                          :token token}])}
               [:i.fa.fa-times-circle]
               [:span " Remove"]]]])]])]]))

(defn artifacts [project-data controls-ch]
 [:div
  [:h2 "Build artifacts for " (vcs-url/project-name (get-in project-data [:project :vcs_url]))]
  [:div.doc
   [:p
    "Circle supports saving files from any build. See "
    [:a {:href "/docs/build-artifacts", :target "_blank"}
     "our build artifact documentation‘"]
    " to set it up."]]])

(defn heroku [user project-data controls-ch]
  (let [project (:project project-data)
        project-id (project-model/id project)
        login (:login user)]
    [:div.heroku-api
     [:h2 "Set personal Heroku API key for " (vcs-url/project-name (:vcs_url project))]
     [:div.heroku-step
      [:h4 "Step 1: Heroku API key"]
      [:div (when (:heroku_api_key user)
              [:p "Your Heroku key is entered. Great!"])
       [:p (:heroku_api_key user)]
       [:div (when-not (:heroku_api_key user)
               ;; XXX pull in set heroku-key from accounts
               (comment (frontend.components.account/heroku user controls-ch)))]
       [:div (when (:heroku_api_key user)
               [:p
                "You can edit your Heroku key from your "
                [:a {:href "/account/heroku"} "account page"] "."])]]]
     [:div.heroku-step
      [:h4 "Step 2: Associate a Heroku SSH key with your account"]
      [:span "Current deploy user: "
       [:strong (or (:heroku_deploy_user project) "none") " "]
       [:i.fa.fa-question-circle
        {:data-bind "tooltip: {}",
         :title "This will affect all deploys on this project. Skipping this step will result in permission denied errors when deploying."}]]
      [:form.api
       (if (= (:heroku_deploy_user project) (:login user))
         (forms/stateful-button
          [:input.remove-user
           {:data-success-text "Saved",
            :data-loading-text "Saving...",
            :on-click #(do (put! controls-ch [:removed-heroku-deploy-user {:project-id project-id}])
                           false)
            :value "Remove Heroku Deploy User",
            :type "submit"}])

         (forms/stateful-button
          [:input.set-user
           {:data-success-text "Saved",
            :data-loading-text "Saving...",
            :on-click #(do (put! controls-ch [:set-heroku-deploy-user {:project-id project-id
                                                                       :login login}])
                           false)
            :value (str "Set user to " (:login user)),
            :type "submit"}]))]]
     [:div.heroku-step
      [:h4
       "Step 3: Add deployment settings to your "
       [:a {:href "/docs/configuration#deployment"} "circle.yml file"] " (example below)."]
      [:pre
       [:code
        "deployment:\n"
        "  staging:\n"
        "    branch: master\n"
        "    heroku:\n"
        "      appname: foo-bar-123"]]]]))

(defn other-deployment [project-data controls-ch]
  [:div
   [:h2
    "Other deployments for " (vcs-url/project-name (get-in project-data [:project :vcs_url]))]
   [:div.doc
    [:p "Circle supports deploying to any server, using custom commands. See "
     [:a {:target "_blank",
          :href "https://circleci.com/docs/configuration#deployment"}
      "our deployment documentation"]
     " to set it up."]]])

(defn subpage-fn [subpage user]
  (get {:parallel-builds parallel-builds
        :env-vars env-vars
        :setup dependencies
        :tests tests
        :hooks chatrooms
        :webhooks webhooks
        :ssh ssh-keys
        :github github-user
        :api api-tokens
        :artifacts artifacts
        :heroku (partial heroku user)
        :deployment other-deployment}
       subpage
       overview))

(defn follow-sidebar [project controls-ch]
  (let [project-id (project-model/id project)
        vcs-url (:vcs_url project)]
    [:div.follow-status
     [:div.followed
      ;; this is weird, but it's what the css expectss
      (when (:followed project)
        (list
         [:i.fa.fa-group]
         [:h4 "You're following this repo"]
         [:p
          "We'll keep an eye on this and update you with personalized build emails. "
          "You can stop these any time from your "
          [:a {:href "/account"} "account settings"]
          "."]
         (forms/stateful-button
          [:button {:on-click #(put! controls-ch [:unfollowed-project {:vcs-url vcs-url
                                                                       :project-id project-id}])
                    :data-loading-text "Unfollowing..."}
           "Unfollow"])))]
     [:div.not-followed
      (when-not (:followed project)
        (list
         [:h4 "You're not following this repo"]
         [:p
          "We can't update you with personalized build emails unless you follow this project. "
          "Projects are only tested if they have a follower."]
         (forms/stateful-button
          [:button {:on-click #(put! controls-ch [:followed-project {:vcs-url vcs-url
                                                                     :project-id project-id}])
                    :data-loading-text "Following..."}
           "Follow"])))]]))

(defn project-settings [data owner]
  (reify

            [:div.project-settings-inner
             (common/flashes)
             [:div#subpage
              (condp = subpage
                :parallel-builds (om/build parallel-builds project-data)
                :env-vars (om/build env-vars project-data)
                :setup (om/build dependencies project-data)
                :tests (om/build tests project-data)
                :hooks (om/build chatrooms project-data)
                :webhooks (om/build webhooks project-data)
                :ssh (om/build ssh-keys project-data)
                :github (om/build github-user project-data)
                :api (om/build api-tokens project-data)
                :artifacts (om/build artifacts project-data)
                :heroku (om/build heroku {:project-data project-data :user user})
                :deployment (om/build other-deployment project-data)
                (om/build overview project-data))]]
            (om/build follow-sidebar (:project project-data))]))))))
