(function($) {
    $.fn.vRenderList = function(options) {

        if (this.length > 1) {
            alert("vRenderList can only be applied to a single DOM element");
            return false;
        }

        //an element can only have one instance of a datasource
        return this.each(function() {
            var element = $(this);

            if (options.name == '') {
                alert("vRenderList needs a unique name");
                return;
            }

            var lookfor = "vRenderer-" + options.name;

            // Return early if this element already has a plugin instance
            if (element.data(lookfor)) {
                vLog('vRenderer', '(vRenderList) already instantiated!');
                return;
            }
            // pass options to plugin constructor
            var vrs = new vRenderList(this, options);

            // Store plugin object in this element's data
            element.data(lookfor, vrs);

            $(document).trigger('vnx-reg-vrenderer', vrs);

        });
    };


    var vRenderList = function(element, options) {
        element = $(element);

        var config = {
            name: '',
            templateID: '',             //id of the fragment
            selectedtemplateID: '',     //we can render a different template for the selected item
            fragmentType: '',
            fragmentClass: '',          //generic classes to add to each fragment
            selectedClass: ''           //we can add a class to the selected fragment
        };

        $.extend(config, options); //extend them by any passed options

        var Us = this;
        var OurNexus = null;
        var dc = function(a) { return document.createElement(a); };

        this.applyto = function() {
            return config.name;
        }

        //we get to initialise all the elements with this particular tooltip class
        this.initialiserenderer = function() {
            OurNexus = $(document).data('vnexus');
            vLog('vRenderList', 'Initialised ' + Us.applyto());
        }


        this.settemplate = function(newtemplate) {
            if (config.templateID != newtemplate) {
                //set the template
                config.templateID = newtemplate;
                //refresh any nexus that uses us
            }
        }

        // Render a range from start to finish into a container
        //      targetID is the element to render into

        this.render = function(whichdatasource, currentselectionkey, start, pagesize) {

            //var $target = $('#' + targetID);
            var startIndex = start;
            var endIndex = start + pagesize;

            var alldata = whichdatasource.getdata();
            var keyfield = whichdatasource.getkeyfield();
            var $container = $(dc('div'));

            //if no data then just return
            if (alldata == null) return null;

            var dataset = alldata.data;

            //make sure we don't go overbounds
            if (endIndex > dataset.length) endIndex = dataset.length;

            for (var i = startIndex; i < endIndex; i++) {
                var selectedone = false;
                //get the single data item from the data
                var dataitem = dataset[i];
                //if there's no data then break out of this
                if (dataitem == null) break;
                //compare the string version of idkey to the current selection
                var idkey = dataitem[keyfield];
                if ((idkey + '') == currentselectionkey) selectedone = true;
                //get the templateID to use either from the local data or the config options
                var templatename = '#' + (dataitem.vnxtemplateID != null ? dataitem.vnxtemplateID : config.templateID);
                //is there a different template for the selected one?
                if (selectedone && config.selectedtemplateID != "") templatename = '#' + config.selectedtemplateID;
                //render a single fragment
                if (templatename == '#') {
                    alert("vRenderList: no template to render");
                    return false;
                }

                var r = vRender(templatename, $(templatename).html(), dataitem, dataset); //render a single template

                var $frag = $(dc(config.fragmentType)).addClass(config.fragmentClass).attr('data-frag-id', idkey).append(r);
                if (selectedone) $frag.addClass(config.selectedClass);

                //add the fragment to the target
                $container.append($frag);
            }

            return $container;
        };

        // Render a single element, return this element 
        this.renderfragment = function(dataitem, dataset, includefragment) {
            var templatename = '#' + (dataitem.templateID != null ? dataitem.templateID : config.templateID);
            if (templatename = '#') {
                alert("vRenderList: no template to render");
                return false;
            }
           
            var r = vRender(templatename, $(templatename).html(), dataitem, dataset);
            //if no fragment needed just return
            if (includefragment == false) return r;
            //otherwise encapsulate this in a fragement and return
            return $(dc(config.fragmentType)).addClass(config.fragmentClass).attr('data-frag-id', dataitem[datasource.getkeyfield()]).append(r);
        };

        //render into a given template and a given data position (either a number or a command)
        this.rendertemplate = function(templateID, dataset, dataitem, wrapinfragment) {

            if (dataset == null || dataitem == null) return null;
            var templatename = '#' + templateID;

            var rendered = vRender(templatename, $(templatename).html(), dataitem, dataset);
            if (wrapinfragment) {
                return $(dc(config.fragmentType)).addClass(config.fragmentClass).addClass(config.replaceClass).html(rendered).attr('data-frag-id', 0);
            }
            return rendered;
        };

        /*  //which page as part of this data
        this.setpage = function(pagenumber) {
        var cp = config.displayPage;

            config.displayPage = pagenumber;
        if (config.displayPage < 0) config.displayPage = 0;
        //also check the upper bound

            if (config.displayPage != cp) return true; //yes we've changed it
        return false; 							//no, the page hasn't changed

        };

        //page the data (the start point) by this amount
        this.page = function(amount) {
        var cp = config.displayPage;
        config.displayPage += amount;
        if (config.displayPage < 0) config.displayPage = 0;

            if (config.displayPage != cp) return true; //yes we've changed it
        return false; 							//no, the page hasn't changed
        };

        this.setselected = function(selectedkey) {
        //we have to set the page to whereever the new selected key is, if the nexus needs rerendering we return true
        if (config.currentselection != selectedkey) {
        //set our local current selection
        config.currentselection = selectedkey;
        return true;
        }
        return false;
        };

        this.getselected = function() {
        return config.currentselection;
        }

        //which page as part of this data
        this.getpage = function() {
        return (config.displayPage);
        };
        */


        Us.initialiserenderer();

    }

})(jQuery);


