/*
 * debug 
 */ 
(function ($) { 
    var searchMash,
        mashConfig;

    window.searchMash = searchMash = window.searchMash || {};
    searchMash.util = searchMash.util || {};

    mashConfig = searchMash.config = searchMash.config || { debug: true };

    function dbg () {
        if (mashConfig && mashConfig.debug)  { 
            dbg_panel.apply (this, arguments);
            dbg_console.apply (this, arguments);
        }
    }

    function dbg_panel () {
        var panel = searchMash.debug_panel;

        if (panel && panel.log) {
            panel.log (Array.prototype.join.call (arguments, " "));
        }
    }

    function dbg_console () {
        var console = window.console,
            buffer = [];

        if ( ! console  ) { return; }

        $.each (arguments, function (key,value) {
            var type = typeof value;
            if ( type === "string" || this instanceof String ) {
                buffer.push (value);
            } else if ( typeof value === "number" || this instanceof Number ) {
                buffer.push (value);
            } else if (typeof value === "boolean" || this instanceof Boolean) {
                buffer.push (value);
            } else {
                if ( buffer.length ) {
                    console.log (buffer.join(" "));
                    buffer = [];
                }
                console.log (value);
            }
        });

        if ( buffer.length ) {
            console.log (buffer.join(" "));
        }
    }

    searchMash.dbg = dbg;
}) (jQuery);

/*
 * DEBUG Panel 
 */

// depends: jQuery, jQuery.cookie 
(function ($) {

    var searchMash = window.searchMash,
        mashConfig = searchMash.config,
        dbg = searchMash.dbg,
        cookie_name = "dbgp";

    function getSetBoolean (input, new_val) {
        if (new_val !== undefined) {
            input.get (0).checked = !! new_val;
        } else {
            return input.get(0).checked;
        }
    }

    function getSetNumber (input, new_val) {
        if (new_val !== undefined) {
            input.val (new_val);
        } else {
            return parseFloat (input.val ());
        }
    }

    function getSetText (input, new_val) {
        if (new_val !== undefined) {
            input.val (new_val);
        } else {
            return input.val ();
        }
    }

    function getterSetterFor (val) {
        if (typeof val == "boolean" || val instanceof Boolean) {
            return getSetBoolean;
        } else if (typeof val == "number" || val instanceof Number) {
            return getSetNumber;
        } else {
            return getSetText;
        }
    }

    function setInputType (val,input) {
        if (typeof val == "boolean" || val instanceof Boolean) {
            input.attr ({type: "checkbox"});
        } else {
            input.attr ({type: "text"});
        }
    }

    /* **************************************** */
    function DebugPanel () {
        this.ns = {};
        this.ns.elements = {};
        var ns = this.ns,
            e,
            debug_panel = this;

        e = ns.elements = {
            container:  $("<div/>").addClass ("debug_panel"),
            resize:     $("<div/>").addClass ("main_resize"),
            content:    $("<div/>"),
            title:      $("<div/>")
                        .text ("debug window")
                        .addClass ("title")
                        .addClass ("main_title")
        };

        e.content
            .addClass ("debug_content")
            .appendTo (e.resize);
        e.container
            .append (e.title)
            .append (e.resize);

        ns.append_funcs = [];
        e.log_window = this.makeBlock ({
            name: "log output",
            classname: "log"
        });

        ns.section = 0;
        this.container = e.container;

        var d = window.document,
            open_debug_link = $("<a/>"),
            close_debug_link = $("<a/>");

        debug_panel
            .bind ("show", function () { 
                open_debug_link.hide ();
            })
            .bind ("hide", function () { 
                open_debug_link.show ();
            })
            .showIfCookie ()
            .appendTo ("#searchmash-contents")
            .log ("go!");

        open_debug_link
            .attr ({ id: "open_debug_link", href: "" })
            .text ("show debug window")
            .click (function () { 
                try { debug_panel.show (); } catch (e) {dbg(e);}
                return false;
            })
            .appendTo ("body");

        close_debug_link
            .attr ({id: "close_debug_link", href: ""})
            .click (function () { 
                try { debug_panel.hide (); } catch (e) {dbg(e);}
                return false;
            })
            .text ("close [x]")
            .prependTo (".debug_panel .main_title");

        return this;
    }

    // copy trigger () and bind () from jQuery.
    $.each (["trigger", "bind"], function (k,v) {
        DebugPanel.prototype[v] = function () {
            $.fn[v].apply (this.container, arguments);
            return this;
        };
    });

    jQuery.extend (DebugPanel.prototype, {
        appendTo: function (target) {
            var ns = this.ns,
                debug_panel = this,
                e = ns.elements,
                append_funcs = ns.append_funcs;

            e.container
                .appendTo (target)
                .draggable ({
                    handle: e.title,
                    stop: function () { 
                        debug_panel.setCookie ();
                    }
                });
            e.resize
                .resizable ({
                    stop: function (ev, ui) {
                        var it = e.content,
                            inner_height = it.innerHeight (),
                            scroll_height = it.get (0).scrollHeight;

                        if (inner_height >= scroll_height)  {
                            e.resize
                                .css ({height: "auto"});
                        }
                    }
                });
            e.content
                .sortable ({
                    axis: 'y',
                    handle: ".block_title"
                });

            $.each (append_funcs, function (k,v) {
                if ( typeof v === "function" ) {
                    v ();
                }
            });
            return this;
        },

        showIfCookie: function () {
            var action = $.cookie (cookie_name) ? "show" : "hide";
            this[action].call (this);
            return this;
        },

        show: function () {
            var where = $.cookie (cookie_name),
                top, left;

            where = where && where.split (":");
            if (where) { 
                this.container.css ({ 
                    top: parseInt (where[0],10) || 0,
                    left: parseInt (where[1],10) || 0
                });
            } else { 
                this.setCookie ();
            }

            this.ns.elements.container.show ();
            this.trigger ("show");
            return this;
        },

        hide: function () {
            this.ns.elements.container.hide ();
            $.cookie (cookie_name,null);
            this.trigger ("hide");
            return this;
        },

        setCookie: function () { 
            var top = this.container.css ("top"),
                left = this.container.css ("left");

            $.cookie (cookie_name, top + ":" + left);
        },

        // TODO have this return an object which allows for better access to
        // the block components. 
        // TODO have block object have a spearate icon object which can be
        // placed in the icon area of the debug panel
        makeBlock: function (opts) {
            var ns = this.ns,
                e = ns.elements,
                append_funcs = ns.append_funcs,
                block   = $("<div/>").addClass ("block"),
                title   = $("<div/>").addClass ("block_title"),
                resize  = $("<div/>").addClass ("block_resize"),
                content = $("<div/>").addClass ("block_content"),
                scroll  = $("<div/>").addClass ("block_scroll");

            opts = $.extend (
                {
                    name:      "section " + ns.section ++
                },
                opts || {}
            );

            title
                .text (opts.name)
                .click (function () { block.toggleClass ("closed"); });

            scroll
                .append (content)
                .appendTo (resize);

            block
                .addClass (opts.classname)
                .append (title)
                .append (resize)
                .appendTo (e.content);

            // have to delay setting resiable until we're in the dom.
            append_funcs.push (function () {
                resize.resizable ({
                    handles: 's',

                    stop:  function () {

                        // first reset the width setting
                        resize.css ({width: null});

                        // ok, now set the height setting so it isn't bigger
                        // than the stuff inside it.

                        // TODO do this much better.. currently resize handles seem
                        // to get in weird spots.
                        var content_height = content.outerHeight (true),
                            resize_height = resize.height ();

                        if (content_height < resize_height) {
                            resize.css ({ height: "auto" });
                            (function setHeight () {
                                var new_height = resize.height ();
                                if (resize_height == new_height) {
                                    // we haven't updated yet. try again later.
                                    setTimeout (setHeight,50);
                                }
                                // ok now fix the height to the size we jumped to
                                // so that overflow settings work
                                resize.css ({height: new_height});
                           }) ();
                        }
                    }
                });
            });

            return content;
        },

        makeSettingsBlock: function (name, classname, settings) {
            var lunge = this.makeBlock ({
                    name: name,
                    classname: classname
                });

            $.each (settings, function (k,v) {
                var input = $("<input>"),
                    label = $("<span>")
                        .text (k + ":"),
                    get = getterSetterFor (v),
                    set = get;

                setInputType (v,input);
                set (input, v);

                input
                    .change (function () {
                        // set it
                        settings[k] = get (input);
                        set (input, settings[k]);

                        // signal change
                        label.toggleClass ("ack");

                        setTimeout (function () {
                            label.toggleClass ("ack"); 
                        }, 100);

                        dbg ("changed " + k + " to " + settings[k] );
                    });

                $("<p/>")
                    .append (label)
                    .append (" ")
                    .append (input)
                    .appendTo (lunge);
            });
            return lunge;
        },

        log: function (msg) {
            var log_window = this.ns.elements.log_window,
                log_elem = log_window.parent().get(0);

            $("<p/>")
                .text (msg)
                .appendTo (log_window);

            // TODO don't scroll down if we're not already scrolled down.
            log_elem.scrollTop = log_elem.scrollHeight;

            return this;
        }


    });

    function init () {
        $(document).ready (function () { 
            var debug_panel;

            if (mashConfig.debug) { 
                debug_panel = searchMash.debug_panel = new DebugPanel ();
                $("head") 
                    .trigger ("searchMash_DebugPanel_start", [debug_panel]);
            }
        });
    }

    searchMash.initDebugPanel = init;


}) (jQuery);

/*
 * Debug for lunge settings
 */ 
(function () {
    var mashConfig = searchMash.config;
    function debug_init_lunge (e, debug_panel) { 
        if (mashConfig.lunge_settings) { 
            debug_panel.makeSettingsBlock (
                "lunge settings",
                "lunge",
                mashConfig.lunge_settings );
        }
    }

    $("head") 
        .bind ("searchMash_DebugPanel_start", debug_init_lunge);
}) ();


/* 
 *  Debug for G Auto Completion [GAC]
 */
(function ($) {

    function debug_init_GAC  (e, debug_panel) {
        var block,
            GAC = searchMash.GAC,
            options,
            input;

        if (GAC && GAC.options && GAC.input) { 
            input = GAC.input;
            options = GAC.options;
        } else { 
            // TODO don't try forever? 
            setTimeout (function () { debug_init_GAC (e, debug_panel);}, 100);
            return;
        }

        block = debug_panel.makeBlock ({ 
            name: "auto suggest",
            classname: "auto_suggest"
        });

        block.append ("width: ");

        $("<a/>")
            .text (options.width || "default" )
            .attr ({href: ""})
            .click (function () { 
                if (options.width == "auto") { 
                    options.width = 0;
                } else { 
                    options.width = "auto" ;
                }

                $(this).text (options.width || "width of input");
                input.setOptions (options);

                return false;
            })
            .appendTo (block);
    }

    $("head") 
        .bind ("searchMash_DebugPanel_start", debug_init_GAC);

}) (jQuery);
