'use strict';

var identity    = require('es5-ext/function/i')
  , d           = require('d/d')
  , memoize     = require('memoizee/lib/regular')
  , memoizeDesc = require('memoizee/lib/d')(memoize)
  , DbjsError   = require('../error')
  , serialize   = require('../serialize/key')

  , defineProperties = Object.defineProperties
  , filterValue = function (value) { return value == null; }
  , filterNull = function (value) { return value != null; }
  , resolveFilter;

require('memoizee/lib/ext/resolvers');

resolveFilter = memoize(function (filter) {
	if (filter === undefined) return filterNull;
	if (filter === null) return filterValue;
	if (typeof filter === 'function') return filter;
	return function (value) { return value === filter; };
});

module.exports = function (setProto) {
	return defineProperties(setProto, memoizeDesc({
		filterByKey: d(function (key, filter) {
			var sKey = serialize(key), set;
			if (sKey == null) {
				throw new DbjsError(key + " is invalid key", 'INVALID_KEY');
			}
			set = this.filter(function (obj) {
				var observable, current;
				observable = obj._getObservable_(sKey);
				observable.on('change', function (event) {
					var value = event.newValue;
					value = Boolean(filter(value, obj));
					if (value === current) return;
					set.refresh(obj);
				});
				(current = Boolean(filter(observable.value, obj)));
				return current;
			});
			return set;
		}, {
			resolvers: [identity, resolveFilter],
			cacheName: '__filterByKey__',
			desc: ''
		})
	}));
};

// Temporary hack
// (until we solve mixed configuration of observable and read only sets)
module.exports(require('observable-set/create-read-only')(
	require('observable-set')
).prototype);

@@ -154,48 +154,150 @@
 oize
-Desc = require('memoizee/lib/d')(memoize
+Prim = require('memoizee/lib/primitive')%0A  , memoizeDesc = require('memoizee/lib/d')(memoize)%0A  , map         = require('observable-value/map'
 )%0A  
@@ -543,24 +543,76 @@
  != null; %7D%0A
+  , byObjId = function (obj) %7B return obj.__id__; %7D%0A
   , resolveF
@@ -1060,24 +1060,33 @@
 ze(key), set
+, observe
 ;%0A%09%09%09if (sKe
@@ -1175,25 +1175,29 @@
 %0A%09%09%09
-set = this.filter
+observe = memoizePrim
 (fun
@@ -1218,103 +1218,44 @@
 %09%09%09%09
-var observable, current;%0A%09%09%09%09observable = obj._getObservable_(sKey);%0A%09%09%09%09observable.on('change'
+return map(obj._getObservable_(sKey)
 , fu
@@ -1262,21 +1262,21 @@
 nction (
-event
+value
 ) %7B%0A%09%09%09%09
@@ -1280,224 +1280,201 @@
 %09%09%09%09
-var value = event.newValue;%0A%09%09%09%09%09value = Boolean(filter(value, obj));%0A%09%09%09%09%09if (value === current) return;%0A%09%09%09%09%09set.refresh(obj);%0A%09%09%09%09%7D);%0A%09%09%09%09(current = Boolean(filter(observable.value, obj)));%0A%09%09%09%09return current;%0A%09%09%09
+return Boolean(filter(value, obj));%0A%09%09%09%09%7D).on('change', function (event) %7B set.refresh(obj); %7D);%0A%09%09%09%7D, %7B serialize: byObjId %7D);%0A%09%09%09set = this.filter(function (obj) %7B return observe(obj).value; 
 %7D);%0A

Fix `filterByKey` logic