
// Context menu
var indexmenu_contextmenu = {'all': []};

/* DOKUWIKI:include scripts/nojsindex.js */
/* DOKUWIKI:include scripts/toolbarindexwizard.js */
/* DOKUWIKI:include scripts/contextmenu.js */
/* DOKUWIKI:include scripts/indexmenu.js */
/* DOKUWIKI:include scripts/contextmenu.local.js */


/* DOKUWIKI:include scripts/fancytree/jquery.fancytree-all.min.js */

//   - page id without URL rewriting http://example.doku/doku.php?id=test:start
//   - page id without URL rewriting http://example.doku/doku.php?id=test:plugins#interwikipaste
//   - page id with .htaccess URL rewriting http://example.doku/test:plugins
//   - page id with .htaccess URL rewriting and 'useslash' config http://example.doku/test/plugins
//   - page id with internal URL rewriting http://example.doku/doku.php/test:plugins
//   - http://example.doku/lib/exe/detail.php?id=test%3Aplugins&media=ns:image.jpg
//   - http://example.doku/lib/exe/fetch.php?w=400&tok=097122&media=ns:image.jpg
//   - http://example.doku/lib/exe/fetch.php?media=test:file.pdf
//   - http://example.doku/_detail/ns:image.jpg?id=test%3Aplugins
//   - http://example.doku/_media/test:file.pdf
//   - http://example.doku/_detail/ns/image.jpg?id=test%3Aplugins
//   - http://example.doku/_media/test/file.pdf


jQuery(function(){  // on page load
    // Create the tree inside the <div id="tree"> element.
    const predefinedPresets = {
        'bootstrap': { //works with template bootstrap3 or by manually adding resources to icon plugin assets
            'preset': 'bootstrap3',
            'map': {}
        },
        'bootstrap-n': { //works with template bootstrap3 or ..etc
            'preset': 'bootstrap3',
            'map': {}
        },
        'awesome': { //works with icons-plugin, settings: enable plugin»icons»loadFontAwesome
            'preset': 'awesome4', //plugin icons does include only awesome4, not awesome5.
            'map': {}
        },
        'material': { // add Material Icons font stylesheet to header with TPL_METAHEADER_OUTPUT in action component
            'preset': 'material',
            'map': {}
        },
        'mdi': { //works with icons-plugin, settings: enable plugin»icons»loadMaterialDesignIcons
            'preset': '',
            'map': {
                _addClass: "mdi",
                checkbox: "mdi-checkbox-blank-outline",
                checkboxSelected: "mdi-check-box-outline",
                checkboxUnknown: "mdi-checkbox-intermediate fancytree-helper-indeterminate-cb",
                dragHelper: "mdi-play",
                dropMarker: "mdi-skip-forward",
                error: "mdi-warning",
                expanderClosed: "mdi-chevron-right",
                expanderLazy: "mdi-chevron-right",
                expanderOpen: "mdi-chevron-down",
                // We may prevent wobbling rotations on FF by creating a separate sub element:
                loading: "mdi-refresh",
                nodata: "mdi-information-outline",
                noExpander: "",
                radio: "mdi-radiobox-blank", // "fa-circle-o"
                radioSelected: "mdi-radiobox-marked",
                // Default node icons.
                // (Use tree.options.icon callback to define custom icons based on node data)
                doc: "mdi-file-outline",
                docOpen: "mdi-file-outline",
                folder: "mdi-folder",
                folderOpen: "mdi-folder-open",
            }
        },
        'typicons': { //works with icons-plugin, settings: enable plugin»icons»loadTypicons
            'preset': '',
            'map': {
                _addClass: "typcn",
                checkbox: "typcn-media-stop-outline",
                checkboxSelected: "typcn-input-checked",
                checkboxUnknown: "typcn-media-stop-outline fancytree-helper-indeterminate-cb",
                dragHelper: "typcn-media-play-outline",
                dropMarker: "typcn-media-fast-forward-outline",
                error: "typcn-warning",
                expanderClosed: "typcn-media-play",
                expanderLazy: "typcn-media-play",
                expanderOpen: "typcn-arrow-sorted-down",
                // We may prevent wobbling rotations on FF by creating a separate sub element:
                loading: "typcn-arrow-sync",
                nodata: "typcn-info-large",
                noExpander: "",
                radio: "typcn-media-record-outline", // "fa-circle-o"
                radioSelected: "typcn-media-record",
                // Default node icons.
                // (Use tree.options.icon callback to define custom icons based on node data)
                doc: "typcn-document",
                docOpen: "typcn-document",
                folder: "typcn-folder",
                folderOpen: "typcn-folder-open",
            }
        }

    };
    // userDefinedPresets can be defined in conf/userscript.js
    const presets = {...predefinedPresets, ...(typeof userDefinedPresets === 'undefined' ? [] : userDefinedPresets)};
    //let targettype;
    // function logEvent(event, data, msg){
    //     //        var args = Array.isArray(args) ? args.join(", ") :
    //     msg = msg ? ": " + msg : "";
    //     jQuery.ui.fancytree.info("Event('" + event.type + "', node=" + data.node + ")" + msg);
    // }
    jQuery(".indexmenu_js2").each(function(){
        let $tree = jQuery(this),
            id = $tree.attr('id');
        const options = $tree.data('options');
        // console.log("options");
        // console.log(options);
        let themePreset = presets[options.opts.theme];
        let targettype; //to share type between handlers
        let extensions = [];
        if(themePreset) {
            extensions.push("glyph");
        }
        if(options.opts.persist) {
            extensions.push("persist");
        }

        $tree.fancytree({
            //enabled extensions
            extensions: extensions,
            //settings for glyph extension
            glyph: {
                preset: themePreset ? themePreset.preset : '',
                map: themePreset ? themePreset.map : {}
            },
            // 0=quite, 1=only errors, upto 4=also debug
            //debugLevel: 4,
            //settings for persist extension
            persist: {
                expandLazy: true,
                // fireActivate: false,    // false: suppress `activate` event after active node was restored
                // overrideSource: false,  // true: cookie takes precedence over `source` data attributes.
                store: "auto" // 'cookie', 'local': use localStore, 'session': sessionStore
                // Sample for a custom store:
                // store: {
                //   get: function(key){ this.info("get(" + key + ")"); return window.sessionStorage.getItem(key); },
                //   set: function(key, value){ this.info("set(" + key + ", " + value + ")"); window.sessionStorage.setItem(key, value); },
                //   remove: function(key){ this.info("remove(" + key + ")"); window.sessionStorage.removeItem(key); }
            },
            // number of levels already expanded, and not unexpandable.
            //minExpandLevel: 2,
            // expand with single click instead of dblclick
            clickFolderMode: 3,
            // closes other opened nodes, so only one node is opened
            //autoCollapse: true,
            // for keyboard..  --opening folders becomes jumpy
            //autoScroll: true,
            // Looping in combination with clicking
            autoActivate: false,
            // disabled because it causes also autoscrolling, such that select node is out-of-view
            activeVisible: false,

            escapeTitles: false,
            tooltip: true,
            //use same setting as wiki page
            rtl: jQuery('html[dir=rtl]').length,

            //for keyboard control
            keydown: function (event, data) {
                switch (event.which) {
                    case 32: // [space]
                        // logEvent(event,data);
                        break;
                    case 13: // [enter]
                        // logEvent(event,data);
                        if(data.node.data.url){
                            // console.log('redirect');
                            window.location.href = data.node.data.url;
                        }
                        break;
                }
            },

            //store in click some event data for the activate handler
            click: function(event, data) {
                // return false to prevent default behavior (i.e. activation, ...)
                targettype = data.targetType; //store target type, only available in click handler
            },

            //go to wiki page if node is activated
            activate: function(event, data){
                const node = data.node;

                //prevent looping (hns is false or a page id)
                if(node.key === JSINFO.id || node.data.hns === JSINFO.id) {
                    //node is equal to current page, prevent to follow the url
                    return;
                }
                if(options.opts.nopg && node.key === JSINFO.namespace + ':') {
                    //nopg marks parent ns node active, prevent to follow the url
                    return;
                }

                // expander should not follow link
                if(targettype === 'expander') {
                    targettype = false; //reset
                    return false;
                }

                if(node.data.url === false) {
                    return false;
                }

                if(node.data.url){
                    window.location.href = node.data.url;
                }
            },

            // active marked node (=current page)
            init: function(event, data) {
                //activate current node
                data.tree.reactivate();
            },
            //add url
            enhanceTitle: function(event, data) {
                let node = data.node;

                if(node.data.url === false) {
                    return;
                }
                if(node.data.url) { // pagename 0 has url /0
                    //nopg has potentially not existing pages
                    let cls = '';
                    if(node.data.hnsNotExisting) {
                        cls = ' class="wikilink2"';
                    }
                    data.$title.html("<a href='" + node.data.url + "'"+cls+">" + node.title + "</a>");
                }
            },
            //retrieve initial data
            source: {
                url: DOKU_BASE + 'lib/exe/ajax.php',
                data: {
                    ns: options.ns,
                    call: 'indexmenu',
                    req: 'fancytree',

                    level: options.opts.level, //only init
                    nons: options.opts.nons ? 1 : 0, //only init; without ns, no lower levels possible
                    nopg: options.opts.nopg ? 1 : 0,
                    subnss: options.opts.subnss, //subns to open. Only on init array, later just current ns string
                    navbar: options.opts.navbar ? 1 : 0, //only init: open tree at current page
                    currentpage: JSINFO.id,
                    max: options.opts.max, //#n of max#n#m
                    skipns: options.opts.skipns,
                    skipfile: options.opts.skipfile,
                    sort: options.sort.sort ? options.sort.sort : 0, //'t', 'd', false TODO is false handled correctly?
                    msort: options.sort.msort ? options.sort.msort : 0, //'indexmenu_n', or metadata 'key subkey' TODO is empty handled correctly?
                    rsort: options.sort.rsort ? 1 : 0,
                    nsort: options.sort.nsort ? 1 : 0,
                    hsort: options.sort.hsort ? 1 : 0,

                    init: 1
                }
            },
            //retrieve data of expanded nodes
            lazyLoad: function(event, data) {
                const node = data.node;
                // Issue an Ajax request to load child nodes
                data.result = {
                    url: DOKU_BASE + 'lib/exe/ajax.php',
                    data: {
                        ns: node.key, // ns with trailing :
                        call: 'indexmenu',
                        req: 'fancytree',

                        level: 1, //level opened nodes, for follow up ajax requests only next level, so:1
                        nons: options.opts.nons ? 1 : 0,
                        nopg: options.opts.nopg ? 1 : 0,
                        subnss: '', //options.opts.subnss is used on init
                        currentpage: JSINFO.id,
                        max: options.opts.maxajax, //#m of max#n#m
                        skipns: options.opts.skipns,
                        skipfile: options.opts.skipfile,
                        sort: options.sort.sort ? options.sort.sort  : 0,
                        msort: options.sort.msort ? options.sort.msort : 0,
                        rsort: options.sort.rsort ? 1 : 0,
                        nsort: options.sort.nsort ? 1 : 0,
                        hsort: options.sort.hsort ? 1 : 0,

                        init: 0
                    }
                }
            }
        });

        //hide the fallback nojs indexmenu
        jQuery('#nojs_' + id.substring(6)).css("display", "none");


        // Note: Loading and initialization may be asynchronous, so the nodes may not be accessible yet.

        // On page load, activate node if node.data.href matches the url#href
//         let tree = jQuery.ui.fancytree.getTree("#" + id),
//             path = window.parent && window.parent.location.pathname;
// // console.log(path);
// // console.log('test');
//         if(path) {
//             let arr = path.split('/'); // not reliable with config:useslash?
//             let last = arr[arr.length-1] || arr[arr.length-2];
//             // console.log(arr);
//             // console.log(last);
//
//             // tree.activateKey(last);
//             // var node1=tree.getNodeByKey(last);
//             // console.log(node1);
//             //     node1.setActive();
//             // also possible:
//             //                $.ui.fancytree.getTree("#tree").getNodeByKey("id4.3.2").setActive();
//
//             // tree.visit(function(n) {
//             //     console.log(n.key);
//             //     console.log(n);
//             //     if( n.key && n.key === last ) {
//             //         n.setActive();  //if not using iframes, this creates a loops in combination with activate above
//             //         return false; // done: break traversal
//             //     }
//             // });
//         }
// console.log(tree);
// console.log("test");
//         jQuery.contextMenu({
//             selector: "span.fancytree-title",
//             items: {
//                 // "cut": {name: "Cut", icon: "cut",
//                 //     callback: function(key, opt){
//                 //         var node = jQuery.ui.fancytree.getNode(opt.$trigger);
//                 //         alert("Clicked on " + key + " on " + node);
//                 //     }
//                 // },
//                 "page": {name: "Page", icon: "", disabled: true },
//                 "sep1": "----",
//                 "revs": {name: "Revisions", icon: "ui-icon-arrowreturn-1-w", disabled: false },
//                 "toc": {name: "ToC preview", icon: "ui-icon-bookmark", disabled: false },
//                 "edit": {name: "Edit", icon: "edit", disabled: false },
//                 "hpage": {name: "Headpage", icon: "add", disabled: false},
//                 "spage": {name: "Start page", icon: "add", disabled: false},
//                 "cpage": {name: "Custom page...", icon: "add", disabled: false},
//                 "acls": {name: "Acls", icon: "ui-icon-locked", disabled: false},
//                 "purge": {name: "Purge cache", icon: "loading", disabled: false},
//                 "html": {name: "Export as HTML", icon: "ui-icon-document", disabled: false},
//                 "text": {name: "Export as text", icon: "ui-icon-note", disabled: false},
//                 "sep2": "----",
//                 "ns": {name: "Namespace", icon: "", disabled: true},
//                 "sep3": "----",
//                 "search": {name: "Search...", icon: "ui-icon-search", disabled: false},
//                 "npage": {name: "New page...", icon: "add", disabled: false},
//                 "nshpage": {name: "Headpage here", icon: "add", disabled: false},
//                 "nsacls": {name: "Acls", icon: "ui-icon-locked", disabled: false}
//             },
//             callback: function(itemKey, opt) {
//                 var node = jQuery.ui.fancytree.getNode(opt.$trigger);
//                 alert("select " + itemKey + " on " + node);
//             }
//         });

        // $tree.contextmenu({
        //     delegate: "span.fancytree-title",
        //     autoFocus: true,
        //     //      menu: "#options",
        //     menu: [
        //         {title: "Page", cmd: 'pg'},
        //         {title: "----", cmd: 'pg'},
        //         {title: "Revisions", cmd: "revs", uiIcon: "ui-icon-arrowreturn-1-w"},
        //         {title: "ToC preview", cmd: "toc", uiIcon: "ui-icon-bookmark"},
        //         {title: "Edit", cmd: "edit", uiIcon: "ui-icon-pencil", disabled: false },
        //         {title: "Headpage", cmd: "hpage", uiIcon: "ui-icon-plus"},
        //         {title: "Start page", cmd: "spage", uiIcon: "ui-icon-plus"},
        //         {title: "Custom page...", cmd: "cpage", uiIcon: "ui-icon-plus"},
        //         {title: "Acls", cmd: "acls", uiIcon: "ui-icon-locked", disabled: true },
        //         {title: "Purge cache", cmd: "purge", uiIcon: "ui-icon-arrowrefresh-1-e"},
        //         {title: "Export as HTML", cmd: "html", uiIcon: "ui-icon-document"},
        //         {title: "Export as text", cmd: "text", uiIcon: "ui-icon-note"},
        //         {title: "Namespace", cmd:'ns'},
        //         {title: "----", cmd:'ns'},
        //         {title: "Search...", cmd: "search", uiIcon: "ui-icon-search"},
        //         {title: "New page...", cmd: "npage", uiIcon: "ui-icon-plus"},// children:[]
        //         {title: "Headpage here", cmd: "nshpage", uiIcon: "ui-icon-plus"},
        //         {title: "Acls", cmd: "nsacls", uiIcon: "ui-icon-locked"}
        //     ],
        //     beforeOpen: function(event, ui) {
        //         var node = jQuery.ui.fancytree.getNode(ui.target);
        //         // Modify menu entries depending on node status
        //         $tree.contextmenu("enableEntry", "toc", node.isFolder());
        //         // Show/hide single entries
        //         $tree.contextmenu("showEntry", "pg", !node.isFolder());
        //         $tree.contextmenu("showEntry", "revs", !node.isFolder());
        //         $tree.contextmenu("showEntry", "toc", !node.isFolder());
        //         $tree.contextmenu("showEntry", "edit", !node.isFolder());
        //         $tree.contextmenu("showEntry", "hpage", !node.isFolder());
        //         $tree.contextmenu("showEntry", "spage", !node.isFolder());
        //         $tree.contextmenu("showEntry", "cpage", !node.isFolder());
        //         $tree.contextmenu("showEntry", "acls", !node.isFolder());
        //         $tree.contextmenu("showEntry", "purge", !node.isFolder());
        //         $tree.contextmenu("showEntry", "html", !node.isFolder());
        //         $tree.contextmenu("showEntry", "text", !node.isFolder());
        //
        //         $tree.contextmenu("showEntry", "ns", node.isFolder());
        //         $tree.contextmenu("showEntry", "search", node.isFolder());
        //         $tree.contextmenu("showEntry", "npage", node.isFolder());
        //         $tree.contextmenu("showEntry", "nshpage", node.isFolder());
        //         $tree.contextmenu("showEntry", "nsacls", node.isFolder());
        //
        //         // Activate node on right-click
        //         node.setActive();
        //         // Disable tree keyboard handling
        //         ui.menu.prevKeyboard = node.tree.options.keyboard;
        //         node.tree.options.keyboard = false;
        //     },
        //     close: function(event, ui) {
        //         // Restore tree keyboard handling
        //         // console.log("close", event, ui, this)
        //         // Note: ui is passed since v1.15.0
        //         var node = jQuery.ui.fancytree.getNode(ui.target);
        //         node.tree.options.keyboard = ui.menu.prevKeyboard;
        //         node.setFocus();
        //     },
        //     select: function(event, ui) {
        //         var node = jQuery.ui.fancytree.getNode(ui.target);
        //         alert("select " + ui.cmd + " on " + node);
        //     }
        // });
    });
});


/**
 * Add button action for the indexmenu wizard button
 *
 * @param  {jQuery}   $btn  Button element to add the action to
 * @param  {Array}    props Associative array of button properties
 * @param  {string}   edid  ID of the editor textarea
 * @return {boolean}  If button should be appended
 */
function addBtnActionIndexmenu($btn, props, edid) {
    indexmenu_wiz.init(jQuery('#' + edid));
    $btn.on('click', function () {
        indexmenu_wiz.toggle();
        return false;
    });
    return true;
}


// try to add button to toolbar
if (window.toolbar !== undefined) {
    window.toolbar[window.toolbar.length] = {
        "type": "Indexmenu",
        "title": "Insert the Indexmenu tree",
        "icon": "../../plugins/indexmenu/images/indexmenu_toolbar.png"
    }
}


/**
 *  functions for js index renderer and contextmenu
 */
var IndexmenuUtils = {

    /**
     * Determine extension from given theme dir name
     *
     * @param {string} themedir name of theme dir
     * @returns {string} extension gif, png or jpg
     */
    determineExtension: function (themedir) {
        let extension = "gif";
        let posext = themedir.lastIndexOf(".");
        if (posext > -1) {
            posext++;
            let ext = themedir.substring(posext, themedir.length).toLowerCase();
            if ((ext === "png") || (ext === "jpg")) {
                extension = ext;
            }
        }
        return extension;
    },

    /**
     * Create div with given id and class on body and return it
     *
     * @param {string} id picker id
     * @param {string} cl class(es)
     * @return {jQuery} jQuery div
     */
    createPicker: function (id, cl) {
        return jQuery('<div>')
            .addClass(cl || 'picker')
            .attr('id', id)
            .css({position: 'absolute'})
            .hide()
            .appendTo('body');
    }

};
