/*global Backbone, _ */

if (window.Transistor === undefined) {

window.Transistor = {};

}

(function (transistor) {

var BackboneCollection = (function () {
    return function (options) {
        var Backbone, U, channel, radio, control, H, backbone_collection, collection_interface, control_interface, binder, set;

        Backbone = options.backbone;
        U = options.underscore;
        channel = options.channel;
        radio = options.radio;
        control = options.control;

        H = (function () {
            return {
            };
        }());

        backbone_collection = new Backbone.Collection();
        backbone_collection.on('change', function (model, options) {
            var entry = (model.get('object') || {}),
                id = model.id;

            if (options.from_radiotower === undefined) {
                if (!control) {
                    throw "BackboneCollection is not mutable by user. The model with id "+model.id+" has been changed";
                } else {
                    delete entry.id;
                    control.update(channel, id, entry);
                }
            }
        });

        collection_interface = {
            add: backbone_collection.add,
            remove: backbone_collection.remove,
            reset: backbone_collection.reset,
            set: backbone_collection.set
        };

        control_interface = {
            add: function (entry) { control.insert(channel, entry); },
            remove: function (model) { control.remove(channel, model.id); },
            set: function (collection) { control.set(channel, collection); }
        };
        control_interface.reset = control_interface.set;

        (function (writer) {
            var privatized = true,
                delegate = function (func) {
                writer[func] = (function (name) {
                    return function () {
                        if (privatized) {
                            if (!control) {
                                throw "BackboneCollection is not mutable by user.";
                            } else {
                                control_interface[name].apply(control_interface, arguments);
                            }
                        } else {
                            return collection_interface[name].apply(backbone_collection, arguments);
                        }
                    };
                }(func));
            };

            collection_interface.asPublic = function (public_context) {
                privatized = false;
                public_context();
                privatized = true;
            };

            delegate('add');
            delegate('remove');
            delegate('reset');
            delegate('set');
        }(backbone_collection));

        set = function (collection) {
            collection_interface.asPublic(function () {
                var models = [], i;

                for (i = 0; i < collection.length; i += 1) {
                    models.push(new Backbone.Model(collection[i]));
                }

                backbone_collection.set(models);
            });
        };

        binder = transistor.Binder({
            init: function (collection) {
                set(collection);
                if (options.on_init !== undefined) {
                    options.on_init(backbone_collection);
                }
            },
            set: set,
            insert: function (entry) {
                collection_interface.asPublic(function () {
                    backbone_collection.add(new Backbone.Model(entry));
                });
            },
            update: function (id, entry) {
                collection_interface.asPublic(function () {
                    var model = backbone_collection.get(id);
                    model.clear({silent: true});
                    model.set(entry, {from_radiotower: true});
                });
            },
            remove: function (id) {
                collection_interface.asPublic(function () {
                    var model = backbone_collection.get(id);
                    backbone_collection.remove(model);
                });
            }
        });

        radio.tune(channel, binder);

        return backbone_collection;
    };
}());

if (transistor.Backbone === undefined) {
    transistor.Backbone = {};
}
transistor.Backbone.Collection = BackboneCollection;

}(window.Transistor));