/**
 * @class Ext.ux.data.PagingMemoryProxy
 * @extends Ext.data.proxy.Memory
 * <p>Paging Memory Proxy, allows to use paging grid with in memory dataset</p>
 */
Ext.define('Ext.ux.data.PagingMemoryProxy', {
	extend: 'Ext.data.proxy.Memory',
	alias: 'proxy.pagingmemory',
	alternateClassName: 'Ext.data.PagingMemoryProxy',

	read: function(operation, callback, scope) {
		var reader = this.getReader(),
		result = reader.read(reader.rawData),
		sorters, filters, sorterFn, records;

		scope = scope || this;

		var o_operation_scope = operation.getScope();
		var i_filters = o_operation_scope.filters || {
			items: []
		};

		// filtering
		filters = i_filters.items || [];
		if (filters.length > 0) {
			//at this point we have an array of  Ext.util.Filter objects to filter with,
			//so here we construct a function that combines these filters by ANDing them together
			records = [];

			Ext.each(result.records, function(record) {
				var isMatch = true,
				length = filters.length,
				i;

				for (i = 0; i < length; i++) {
					var filter = filters[i],
					fn = filter.getFilterFn(),
					scope = filter.scope;

					isMatch = isMatch && fn.call(scope, record);
				}
				if (isMatch) {
					records.push(record);
				}
			}, this);

			result.records = records;
			result.totalRecords = result.total = records.length;
		}

		// sorting
		sorters = o_operation_scope.sorters.items || [];
		if (sorters.length > 0) {
			//construct an amalgamated sorter function which combines all of the Sorters passed
			sorterFn = function(r1, r2) {
				var result = sorters[0].sort(r1, r2),
				length = sorters.length,
				i;

				//if we have more than one sorter, OR any additional sorter functions together
				for (i = 1; i < length; i++) {
					result = result || sorters[i].sort.call(this, r1, r2);
				}

				return result;
			};

			result.records.sort(sorterFn);
		}

		// paging (use undefined cause start can also be 0 (thus false))
		if (operation.getStart() !== undefined && operation.getLimit() !== undefined) {
			result.records = result.records.slice(operation.getStart(), operation.getStart() + operation.getLimit());
			result.count = result.records.length;
		}

		Ext.apply(operation, {
			_resultSet: result
		});

		operation.setSuccessful(true);

		Ext.Function.defer(function () {
			Ext.callback(callback, scope, [operation]);
		}, 10);
	}
});
