var Pallette = function()
{
    var current_nodes = null;
    var pallette;

    var current_list = null;
    var current_lis = new Array();
    var current_anchor = null;
    var current_img = null;

    var editable_div = null;

    var _pub = {
        init: function()
        {
            pallette = new Element('div',{id:'pallette'});
            document.body.appendChild(pallette);
            this.refresh();
            new Draggable(pallette,{starteffect:null,endeffect:null});
        },

        refresh: function(active_div)
        {
            current_anchor = null;
            current_img = null;
            current_list = null;
            current_lis = new Array();

            current_nodes = Wrapper.get('selected');

            editable_div = active_div;
            
            Util.removeChildren(pallette);

            if(editable_div == null)
            {
                //Debug.log('refresh passed null div');
                return;
            }

            var actions = parseSelection(current_nodes);
            actions.each(function(i){
                pallette.appendChild(createItem(i));
            });

            if(actions.length)
                pallette.appendChild(new Element('hr'));
            var undo,redo;
            if(undo = editable_div.history.canUndo())
            {
                pallette.appendChild(Util.createButton(
                    'undo ' + undo,
                    'undo ' + undo,
                    function(){
                        //editable_div.history.undo.bind(editable_div.history)();
                        editable_div.history.undo();
                        Pallette.refresh(editable_div);
                    },
                    1,
                    'undo')
                );
            }
            else
                pallette.appendChild(Util.createButton('undo','',function(){},0,'undo'));
            if(redo = editable_div.history.canRedo())
            {
                pallette.appendChild(Util.createButton(
                    'redo ' + redo,
                    'redo ' + redo,
                    function(){
                        //editable_div.history.redo.bind(editable_div.history)();
                        editable_div.history.redo();
                        Pallette.refresh(editable_div);
                    },
                    1,
                    'redo')
                );
            }
            else
                pallette.appendChild(Util.createButton('redo','',function(){},0,'redo'));
        }
    };

    var createItem = function(action)
    {
        var parts = action.split(' ');
        if(parts[0] == 'format')
            return makeAddFormatButton(parts[1],1);
        else if(parts[0] == 'deformat')
            return makeRemoveFormatButton(parts[1],1);
        else if(parts[0] == 'hr')
            return new Element('hr');
        else if(parts[0] == 'edit_link')
            return Util.createButton(
                'edit link',
                'edit the selected link',
                function(){
                    editable_div.history.push('edit link');
                    Editor.edit(current_anchor,RRMark2.finishEdit);
                },
                1,
                'edit_link');
        else if(parts[0] == 'remove_link')
            return Util.createButton(
                'remove link',
                'remove all links from selected text',
                function(){
                    editable_div.history.push('remove link');
                    Format.unLink(current_nodes);
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'remove_link');
        else if(parts[0] == 'create_link')
            return Util.createButton(
                'create link',
                'create a link from the selected text',
                function(){
                    editable_div.history.push('create link');
                    var anchor = Format.link(current_nodes);
                    anchor.addClassName('unsaved');
                    Editor.edit(anchor,function(nodes)
                    {
                        editable_div.history.collapse('create link');
                        RRMark2.finishEdit(nodes);
                    });
                },
                1,
                'create_link');
        else if(parts[0] == 'heading')
            return Util.createButton(
                parts[1],
                'apply heading ' + parts[1] + ' to the selected paragraphs',
                function(){
                    editable_div.history.push('set heading');
                    RRMark2.finishEdit(Format.setHeading(current_nodes,parts[1]));
                    Pallette.refresh(editable_div)
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'heading_' + parts[1]);
        else if(parts[0] == 'create_image')
            return Util.createButton(
                'create image',
                'insert an image into the page',
                function(){
                    editable_div.history.push('create image');
                    var img = new Element('img');
                    img.src = 'images/sample.png';
                    img.addClassName('unsaved');
                    editable_div.appendChild(img);
                    var finishedEdit = function(){
                        img.addClassName('unpositioned');
                        RRMark2.dropImage(img);
                        editable_div.history.collapse('create image');
                    };
                    Editor.edit(img,finishedEdit);
                },
                1,
                'create_image');
        else if(parts[0] == 'edit_image')
            return Util.createButton(
                'edit image',
                'edit the selected image',
                function(){
                    editable_div.history.push('edit image');
                    Editor.edit(current_img);
                },
                1,
                'edit_image');
        else if(parts[0] == 'delete')
            //TODO needs to behave a bit differently if the node being deleted
            //is the descendant of a list item
            return Util.createButton(
                'delete',
                'delete the selected content',
                function(){
                    editable_div.history.push('delete');
                    current_nodes.each(function(n){
                        if(n.parentNode.hasClassName('wrapper'))
                            n.parentNode.remove();
                        else
                            n.parentNode.removeChild(n);
                    });
                    RRMark2.finishEdit(new Array());
                    Format.ensureIntegrity(editable_div);
                    Pallette.refresh(editable_div);
                },
                1,
                'delete');
        else if(parts[0] == 'delistify')
            return Util.createButton(
                'de-listify',
                'move the selected list items up one level',
                function(){
                    editable_div.history.push('de-listify');
                    Format.deListify(current_list,current_lis);
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'de_listify'
            );
        else if(parts[0] == 'join_lists')
            return Util.createButton(
                'join lists',
                'join the selected lists (warning! make sure you have selected adjacent lists)',
                function()
                {
                    editable_div.history.push('join lists');
                    Format.joinLists(current_nodes);
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'join_lists'
            );
        else if(parts[0] == 'join')
            return Util.createButton(
                'join',
                'join headings, paragraphs, list items and break separated lines into a single paragraph',
                function()
                {
                    editable_div.history.push('join');
                    RRMark2.finishEdit(Format.join(current_nodes));
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'join'
            );
        else if(parts[0] == 'listify' || parts[0] == 'sublistify')
            return Util.createButton(
                parts[0] + ' ' + parts[1],
                'turn selected text into a list/sublist',
                function()
                {
                    editable_div.history.push('listify');
                    Format.listify(current_nodes,parts[1]);
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'listify'
            );
        else if(parts[0] == 'brs2ps')
            return Util.createButton(
                'split breaks',
                'turn single line separated text into paragraphs or list items',
                function(){
                    editable_div.history.push('split breaks');
                    RRMark2.finishEdit(Format.setHeading(current_nodes,'none'));
                    Pallette.refresh(editable_div)
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'split_brs');
        else if(parts[0] == 'ps2brs')
            return Util.createButton(
                'join breaks',
                'turn paragraphs or list items into single line separated text',
                function(){
                    editable_div.history.push('join breaks');
                    RRMark2.finishEdit(Format.join(current_nodes,1));
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'join_brs');
        else if(parts[0] == 'list')
            return Util.createButton(
                parts[1],
                'convert selected list into ' + parts[1],
                function(){
                    editable_div.history.push('convert list to ' + parts[1]);
                    Util.relocate(current_list,parts[1]);
                    RRMark2.finishEdit(current_nodes);
                    Pallette.refresh(editable_div);
                    Format.ensureIntegrity(editable_div);
                },
                1,
                'list_style_' + parts[1]);
    };

    //TODO this is really slow
    var parseSelection = function(nodes)
    {
        var nodes_contiguous = TextNode.isContiguous(current_nodes);

        var link_count = 0;
        var img_count = 0;
        var list_count = 0;

        var actions = new Array();
        //var format_actions = new Array();
        var format_actions = new Array();
        var link_actions = new Array();
        var heading_actions = new Array();
        var img_actions = new Array();
        var list_actions = new Array();

        var blocks = new Array();

        if(nodes.length)
        {
            var div = nodes[0].parentNode.up('div.editable');
            if(!div || div.am_empty)
                return new Array();
        }

        nodes.each(function(n)
        {
            if(n.nodeType == 3)
            {
                blocks.push(TextNode.getBlockNode(n));
                if(!n.parentNode)
                {
                    Debug.log('parseSelection found a textnode with no parent!');
                    return;
                }
                //add and remove formats:
                Format.types().each(function(fm){
                    if(Format.isFormatted(n,fm))
                    {
                        if(format_actions.indexOf('format ' + fm) == -1)
                            format_actions.push('deformat ' + fm);
                    }
                    else if (!(n.parentNode.match('a') ||
                        n.parentNode.up('a')))
                    {
                        if(format_actions.indexOf('deformat ' + fm) != -1)
                            format_actions =
                            format_actions.without('deformat ' + fm);
                        format_actions.push('format ' + fm);
                    }
                });

                //add/remove/edit links:
                var new_anchor = null;
                if(n.parentNode.match('a'))
                    new_anchor = n.parentNode;
                else
                    new_anchor = n.parentNode.up('a');

                if(new_anchor)
                {
                    if(new_anchor != current_anchor)
                        link_count++;
                    if(link_count > 1)
                    {
                        current_anchor = null;
                        link_actions = link_actions.without('edit_link');
                    }
                    else
                    {
                        current_anchor = new_anchor;
                        link_actions.push('edit_link');
                    }
                    link_actions.push('remove_link');
                }

                var current_heading = null;
                Format.headings().each(function(h){
                    if(Format.isFormatted(n,h))
                        current_heading = h;
                });
                if(!current_heading)
                    current_heading = 'none';
                var available_headings = 
                    Format.headings().without(current_heading);
                available_headings.each(function(h){
                    var item = 'heading ' + h;
                    heading_actions.push(item);
                });
            }
            else if(n.match('img'))
            {
                //add/edit images:
                img_count++;
                if(img_count > 1)
                {
                    img_actions = img_actions.without('edit_image');
                    current_img = null;
                }
                else
                {
                    img_actions.push('edit_image');
                    current_img = n;
                }
                if(nodes.length == 1)
                {
                    if(n.up('a'))
                    {
                        current_anchor = n.up('a');
                        link_actions.push('edit_link');
                        link_actions.push('remove_link');
                    }
                    else
                        link_actions.push('create_link');
                }
            }
        });

        blocks = blocks.uniq();

        var lists = Util.collectAncestors(nodes,'ul,ol');
        var list_items = Util.collectAncestors(nodes,'li');

        current_lis = list_items;

        if(lists.length > 1)
        {
            var lists_same_depth = true;
            var lists_contiguous = true;
            var depth = lists.first().ancestors().length;
            var prev = lists.first();
            for(var n = 1;n < lists.length; n++)
            {
                if(depth != lists[n].ancestors().length)
                    lists_same_depth = false;
                if(lists[n].previous() != prev)
                    lists_contiguous = false;
                prev = lists[n];
            }
            if(lists_contiguous && lists_same_depth)
                list_actions.push('join_lists');
        }
        else if(lists.length == 1)
        {
            if(lists.first().match('ul'))
                list_actions.push('list ol');
            else
                list_actions.push('list ul');
            current_list = lists.first();
        }

        if(list_items.length)
        {
            var items_contiguous = true;
            var items_same_depth = true;
            var depth = list_items.first().ancestors().length;
            var prev = list_items.first();
            for(var n = 1;n < list_items.length;n++)
            {
                if(depth != list_items[n].ancestors().length)
                    items_same_depth = false;
                if(list_items[n].previous() != prev)
                    items_contiguous = false;
                prev = list_items[n];
            }

            //TODO should be able to delistify when multiple lists are selected
            if(lists.length == 1)
                list_actions.push('delistify');

            //make sure there is some list item we can put the selected
            //items under
            //TODO also check that list items are same depth
            var valid_parent = false;
            list_items.each(function(li)
            {
                if(li.previous() && current_lis.indexOf(li.previous()) == -1)
                    valid_parent = true;
            });
            if(valid_parent && items_contiguous && nodes_contiguous)
            {
                list_actions.push('sublistify ul');
                list_actions.push('sublistify ol');
            }
        }
        else if(nodes.length && nodes_contiguous)
        {
            list_actions.push('listify ul');
            list_actions.push('listify ol');
        }

        img_actions.push('create_image');

        if(link_actions.indexOf('edit_link') == -1 && nodes_contiguous &&
            nodes.length && blocks.length == 1)
            link_actions.push('create_link');

        //combine all actions
        format_actions = format_actions.uniq();
        format_actions = format_actions.sort(function(a,b){
            var _a = a.split(' ')[1];
            var _b = b.split(' ')[1];
            if(_a == _b)
                return 0;
            else
                return _a < _b ? -1 : 1;
        });

        actions = actions.concat(format_actions.uniq());

        if(actions.length && link_actions.length)
            actions.push('hr');
        actions = actions.concat(link_actions.uniq());

        if(actions.length && heading_actions.length)
            actions.push('hr');
        actions = actions.concat(heading_actions.uniq());

        if(actions.length && img_actions.length)
            actions.push('hr');
        actions = actions.concat(img_actions.uniq());

        if(actions.length && list_actions.length)
            actions.push('hr');
        actions = actions.concat(list_actions.uniq());

        if(nodes.length)
        {
            if(actions.length)
                actions.push('hr');
            if(nodes_contiguous)
            {
                actions.push('join');
                actions.push('ps2brs');
            }
            actions.push('brs2ps');
            actions.push('delete');
        }

        return actions;
    };

    var makeAddFormatButton = function(format,enabled)
    {
        var new_button = Util.createButton(
            'add ' + format,
            'add ' + format + ' formatting from the selected text',
            function(){
                editable_div.history.push('format ' + format);
                Format.addFormat(current_nodes,format);
                RRMark2.finishEdit(current_nodes);
            },
            enabled,
            'add_' + format
        );

        return new_button;
    };

    var makeRemoveFormatButton = function(format,enabled)
    {
        var new_button = Util.createButton(
            'remove ' + format,
            'remove ' + format + ' formatting from the selected text',
            function(){
                editable_div.history.push('unformat ' + format);
                Format.removeFormat(current_nodes,format);
                RRMark2.finishEdit(current_nodes);
                //RRMark2.finishEdit(null);
            },
            enabled,
            'remove_' + format
        );

        return new_button;
    };

    return _pub;
}();
