ko.bindingHandlers.slimScrolledForeach = {
    makeTemplateValueAccessor: function(valueAccessor) {
        var modelValue = valueAccessor(),
            unwrappedValue = ko.utils.peekObservable(modelValue),    // Unwrap without setting a dependency here
            result, slimscroll;

        // If unwrappedValue is the array, pass in the wrapped value on its own
        // The value will be unwrapped and tracked within the template binding
        // (See https://github.com/SteveSanderson/knockout/issues/523)
        if ((!unwrappedValue) || typeof unwrappedValue.length === "number") {
            result = { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
            slimscroll = {};
        } else {
            // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
            ko.utils.unwrapObservable(modelValue);
            result =  {
                'foreach': unwrappedValue['data'],
                'as': unwrappedValue['as'],
                'includeDestroyed': unwrappedValue['includeDestroyed'],
                'afterAdd': unwrappedValue['afterAdd'],
                'beforeRemove': unwrappedValue['beforeRemove'],
                'afterRender': unwrappedValue['afterRender'],
                'beforeMove': unwrappedValue['beforeMove'],
                'afterMove': unwrappedValue['afterMove'],
                'templateEngine': ko.nativeTemplateEngine.instance
            };
            slimscroll = unwrappedValue['slimscroll'];
        }

        return {accessor: function() { return result; }, slimscroll: slimscroll};
    },

    slimscroll: function(element, options) {
        options = options || {};
        setTimeout(function() {
            if (element.nodeName === "#comment") {
                // foreach is bound to a virtual element
                $(element.parentElement).slimScroll(options);
            } else {
                $(element).slimScroll(options);
            }
        }, 10);
    },

    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var prepped = ko.bindingHandlers["slimScrolledForeach"].makeTemplateValueAccessor(valueAccessor);
        ko.bindingHandlers["slimScrolledForeach"].slimscroll(element, prepped.slimscroll);
        return ko.bindingHandlers['template']['init'](element, prepped.accessor);
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var prepped = ko.bindingHandlers["slimScrolledForeach"].makeTemplateValueAccessor(valueAccessor);
        var options = $.extend(prepped.slimscroll, {scrollBy: 0});
        ko.bindingHandlers["slimScrolledForeach"].slimscroll(element, options);
        return ko.bindingHandlers['template']['update'](element, prepped.accessor, allBindings, viewModel, bindingContext);
    }
};
ko.virtualElements.allowedBindings.slimScrolledForeach = true;
