content: {-# LANGUAGE FlexibleInstances, OverloadedStrings, QuasiQuotes, RecordWildCards #-}
  {-# OPTIONS_GHC -F -pgmFhsx2hs #-}
  module Clckwrks.NavBar.EditNavBar where
  
  import Clckwrks.Admin.Template (template)
  import Control.Applicative     ((<$>))
  import Clckwrks                (query, update)
  import Clckwrks.NavBar.Acid    (GetNavBar(..), SetNavBar(..))
  import Clckwrks.NavBar.Types   (NavBar(..), NavBarLinks(..), NavBarItem(..))
  import Clckwrks.Monad          (Clck(..), ClckState(..), getNavBarLinks, mapClckT)
  import Clckwrks.Types          (NamedLink(..))
  import Clckwrks.URL            (ClckURL(..), AdminURL(..))
  import Control.Monad.State     (get)
  import Control.Monad.Trans     (lift, liftIO)
  import Data.Aeson              (FromJSON(..), ToJSON(..), Value(..), (.:), (.=), decode, object)
  import Data.Aeson.QQ           (aesonQQ)
  import qualified Data.Text     as T
  import Data.Text.Lazy (Text)
  import Data.Tree               (Tree(..))
  import qualified Data.Vector   as Vector
  import Happstack.Server        (Response, internalServerError, lookBS, ok, toResponse)
  import HSP.XML                 (XML, fromStringLit)
  import HSP.XMLGenerator
  import Language.Javascript.JMacro
  import Web.Routes              (showURL)
  
  editNavBar :: Clck ClckURL Response
  editNavBar =
      do p     <- plugins <$> get
         links <- getNavBarLinks p
  --       liftIO $ print (toJSON links)
         currentNavBar <- query GetNavBar
         template "Edit NavBar" (headers currentNavBar links) $
                  <%>
                   <h1>NavBar Editor</h1>
                     <div id="alert">
                     </div>
                     <div class="form-horizontal">
                      <fieldset>
                       <legend>Add Link</legend>
                       <div class="control-group">
                        <label class="control-label" for="plugin-list">Select a plugin...</label>
                        <div class="controls">
                         <select id="plugin-list"></select><br />
                        </div>
                       </div>
                       <div class="control-group">
                        <label class="control-label" for="navBar-item-list">then select a link</label>
                        <div class="controls">
                         <div class="input-append">
                          <select id="navBar-item-list"></select>
                          <button class="btn" id="add-link">Add Link</button>
                         </div>
                        </div>
                       </div>
                       <div class="control-group">
                        <label class="control-label" for="saveChanges"></label>
                        <div class="controls">
                         <button class="btn btn-success" id="saveChanges"><i class="icon-ok icon-white"></i> Save Changes</button>
                        </div>
                       </div>
                      </fieldset>
  
                      <fieldset>
                       <legend>NavBar</legend>
                       <p><i>Drag and Drop to rearrange. Right-click to rename or remove.</i></p>
                       <div id="navBar"></div>
                      </fieldset>
                     </div>
                  </%>
      where
        headers :: NavBar -> NavBarLinks -> GenChildList (Clck ClckURL)
        headers currentNavBar navBarLinks
             = do navBarUpdate <- showURL (Admin NavBarPost)
                  <%>
                   <link rel="stylesheet" href="/jstree/themes/default/style.min.css" />
                   <script type="text/javascript" src="/jstree/jstree.min.js" ></script>
                   <% [$jmacro|
  //                      function !doubleClickCB(e, dt) {
  //                        alert(dt.rslt.o);
  //                        navBar.rename(d.rslt);
  //                      };
  
                        $(document).ready(function ()
                          { $("#navBar").jstree({ 'core' :
                                                   { 'data'           : `(navBarToJSTree currentNavBar)`
                                                   , 'themes'         : { 'variant' : 'large' }
                                                   , 'check_callback' : true
                                                   }
                                                , 'contextmenu' :
                                                   { 'items' : function (o, cb) {
                                                                  var items    = $.jstree.defaults.contextmenu.items(o, cb);
                                                                  return { 'rename' : items.rename
                                                                         , 'remove' : items.remove
                                                                         };
                                                                }
                                                   }
                                                , 'types' :
                                                   { 'target' :
                                                     { 'icon'         : 'icon-black icon-bookmark'
                                                     , 'max_children' : 0
                                                     }
                                                   }
                                                , 'plugins'          : [ 'contextmenu', 'dnd', 'types' ]
                                                });
  
                            var !navBar = $.jstree.reference("#navBar");
                            `(initializeDropDowns navBarLinks)`;
                            `(removeItem)`;
                            `(saveChanges navBarUpdate)`;
                          });
                      |]
                    %>
                   </%>
  
  initializeDropDowns :: NavBarLinks -> JStat
  initializeDropDowns navBarLinks' =
      [jmacro|
               var !navBarLinks = `(toJSON navBarLinks')`;
               var pluginList = $('#plugin-list');
               var navBarItemList = $('#navBar-item-list');
  
               function populateLinks (pluginIndex) {
                 navBarItemList.empty();
                 for (var i = 0; i < navBarLinks[pluginIndex].pluginLinks.length; i++) {
                   var option = $('<option></option>', { value : [pluginIndex,i] }).text(navBarLinks[pluginIndex].pluginLinks[i].navBarItemName);
                   option.data("navBarItem", navBarLinks[pluginIndex].pluginLinks[i].navBarItemName);
                   navBarItemList.append(option);
                 }
               }
  
               for (var p = 0; p < navBarLinks.length; p++) {
                 var option = $('<option></option>', { 'value' : p }).text(navBarLinks[p].pluginName);
                 option.text(navBarLinks[p].pluginName);
                 pluginList.append(option);
               }
  
               populateLinks(0);
               pluginList.change(function() { populateLinks($(this).val()); });
  
               // add handler to add-link button
               $("#add-link").click(function () {
                 var indexes = navBarItemList.val().split(',');
                 var navBarItem = navBarLinks[indexes[0]].pluginLinks[indexes[1]];
  
                 var entry = { 'state'    : { 'opened' : true }
                             , 'text'     : navBarItem.navBarItemName
                             , 'type'     : 'target'
                             , 'a_attr'   : { 'rel' : 'target' }
                             , 'data' :
                                  { 'link' :
                                       { 'navBarName' : navBarItem.navBarItemName
                                       , 'navBarLink' : navBarItem.navBarItemLink
                                       }
                                  }
                             };
                 navBar.create_node(null, entry, "last",  null, false);
               });
  
             |]
  
  saveChanges :: T.Text -> JStat
  saveChanges navBarUpdateURL =
      [$jmacro|
       $("#saveChanges").click(function () {
         var tree = navBar.get_json('#'); // $("#navBar").jstree("get_json", -1);
         var json = JSON.stringify(tree);
         console.log(json);
         $.post(`(navBarUpdateURL)`, { tree : json });
         var alert = $('<div class="alert alert-success"><button type="button" class="close" data-dismiss="alert">×</button><span>Changes Saved!</span></div>');
  //       alert.alert();
         $("#alert").append(alert);
       });
      |]
  
  
  removeItem :: JStat
  removeItem =
    [$jmacro|
     $("#remove-item").click(function() {
         navBar.remove(navBar.get_selected());
     });
    |]
  
    {-
      object [ "core" .=
               object [ "data" .= navBarToJSTree navBar
                      ]
             , "types" .=
               object [ "#" .=
                        object [ "max_children" .= (-1 :: Int)
                               ]
                      , "navBar" .=
                        object [ "max_children" .= (-1 :: Int)
                               ]
                      , "target" .=
                        object [ "max_children" .= (0 :: Int)
                               , "icon"         .= False
                               ]
                      ]
             , "dnd" .=
                 object [ "drop_target" .= False
                        , "drag_target" .= False
                        ]
             , "ui" .=
                   object [ "initially_select" .= ([ "tree-root" ] :: [String])
                          ]
             , "plugins"   .= ([ "themes", "ui", "crrm", "types", "json_data", "dnd" ] :: [String])
             ]
  -}
  navBarToJSTree :: NavBar -> [Value]
  navBarToJSTree (NavBar items) =
    map navBarItemToJSTree items
  
  navBarItemToJSTree :: NavBarItem -> Value
  navBarItemToJSTree (NBLink NamedLink{..}) =
    [aesonQQ|
       { text : #{namedLinkTitle}
       , type : "target"
       , a_attr : { rel : "target" }
       , data : { link :
                   { navBarLink : #{namedLinkURL}
                   }
                }
  
       } |]
  --  toJSON namedLinkTitle
    {-
      object [ "data" .=
                 object [ "title" .= namedLinkTitle
                        ]
             , "attr" .=
                 object [ "rel" .= ("target" :: String)
                        ]
             , "metadata" .=
                 object [ "link" .=
                            object [ "navBarLink" .= namedLinkURL
                                   ]
                        ]
             ]
  -}
  {-
  jstree :: NavBar -> Value
  jstree navBar = -- #{navBarToJSTree navBar}
    [aesonQQ|
     { core :
         { data           : []
         , themes         : { variant : "large" }
         , check_callback : true
         }
     , types :
         { target :
             { icon         : "glyphicon glyphicon-flash"
             , max_children : 0
             }
         }
     , plugins          : ["contextmenu", "dnd", "types"]
     } |]
  -}
  navBarPost :: Clck ClckURL Response
  navBarPost =
    do t <- lookBS "tree"
       let mu = decode t :: Maybe NavBarUpdate
  --     liftIO $ print t
  --     liftIO $ print mu
       case mu of
         Nothing ->
             do internalServerError $ toResponse ("navBarPost: failed to decode JSON data" :: T.Text)
         (Just (NavBarUpdate u)) ->
             do update (SetNavBar u)
                ok $ toResponse ()
  
  newtype NavBarUpdate     = NavBarUpdate NavBar deriving (Show)
  
  instance FromJSON NavBarUpdate where
    parseJSON (Array a) = (NavBarUpdate . NavBar) <$> mapM parseJSON (Vector.toList a)
  
  instance FromJSON NavBarItem where
    parseJSON (Object o) =
        do ttl        <- o    .: "text"
           meta       <- o    .: "data"
           link       <- meta .: "link"
           navBarLink <- link .: "navBarLink"
           let nl = NamedLink ttl navBarLink
           return (NBLink nl)
  