(ns yenu.routes.admin
  (:require [yenu.layout :as layout]
            [compojure.core :refer [defroutes GET POST]]
            [ring.util.http-response :as response]
            [ring.util.response :refer [redirect]]
            [clojure.java.io :as io]
            [yenu.helpers.images :as images]
            [yenu.db.core :as db]
            [clojure.string :as str])
  (:import [java.io File FileInputStream FileOutputStream]))

(defn decoded-url-file [filepath]
  (java.net.URLDecoder/decode filepath "utf-8"))

(defn upload-file [{:keys [tempfile size filename]}]
  (let [target-filepath (decoded-url-file (images/data-path "to-process" filename))]
    (try
      (with-open [in (new FileInputStream tempfile)
                  out (new FileOutputStream target-filepath)]
        (let [src (.getChannel in)
              dst (.getChannel out)]
          (.transferFrom dst src 0 (.size src))
          (.flush out))))
    target-filepath))

(defn add-tag [image-id tag]
  (db/create-tag! {:tagname tag})
  (let [{tag-id :id} (db/get-tag {:tagname tag})]
    (db/add-tag-to-image! {:imageid image-id :tagid tag-id})))

(defn add-tags-for-image [image-id tag-string]
  (let [all-tags (str/split tag-string, #"(\s*,\s*|\s+)")]
    (run! #(add-tag image-id %) all-tags)))

(defn add-image-to-database [filehash title description tags]
  (let [img (db/create-image! {:hash filehash :title title :description description})
        image-id ((keyword "last_insert_rowid()") img)]
    (add-tags-for-image image-id tags)))

(defn delete-image! [id request]
  (let [image (db/get-image {:id id})]
    (db/delete-image! {:id id})
    (db/delete-image-tags! {:id id})
    (db/delete-image-comments! {:id id})
    (images/delete-image! (:hash image))))

(defn comment-stream []
  (let [comments (db/get-recent-comments {:num-comments 20})]
    (layout/render-file "comments.html" {:comments comments})))

(defn edit-image-form [id request]
  (let [image (db/get-image {:id id})
        tags (db/get-tags-for-image {:id id})]
    (layout/render-file "admin/upload.html" {:image image :tags tags})))

(defn edit-image! [id title description tags request]
  (db/edit-image! {:id id :title title :description description})
  (db/delete-image-tags! {:id id})
  (add-tags-for-image id tags))

(defn image-id-from-comment [id]
  (:image_id (db/get-comment {:id id})))

(defroutes admin-routes
  (GET "/upload" [:as request]
       (-> (layout/render-file
            "admin/upload.html"
            {:flash (:flash request)})))
  (POST "/upload" [file title description tags]
        (let [filename (upload-file file)
              imghash (images/scale-image-and-save filename)]
          (images/remove-temp-image filename)
          (if imghash
            (do
              (add-image-to-database imghash title description tags)
              (-> (redirect "/upload")
                  (assoc :flash {:message "Upload successfull" :type "success"})))
            (-> (redirect "/upload")
                (assoc :flash {:message "Upload failed" :type "danger"})))))

  (GET "/delete/:id" [id :as request]
       (delete-image! id request)
       (-> (redirect "/page/1")
           (assoc :flash {:message "Image deleted" :type "danger"})))

  (GET "/delete-comment/:id" [id]
       (let [image-id (image-id-from-comment id)]
         (db/delete-comment! {:id id})
         (-> (redirect (str "/show/" image-id))
             (assoc :flash {:message "Comment deleted" :type "danger"}))))

  (GET "/edit/:id" [id :as request]
       (edit-image-form id request))

  (POST "/edit/:id" [id title description tags :as request]
        (edit-image! id title description tags request)
        (-> (redirect (str "/show/" id))
            (assoc :flash {:message "Image edited" :type "success"})))

  (GET "/statistics" []
       (layout/render-file "statistics.html"))
  (GET "/comments" []
       (comment-stream)))
