var AttractionsStorage = Class.create({
    initialize: function() {
		console.log('AttractionsStorage::initialize');
		this.isLocked = false;
		this.data = [];
		this.activities = $H({});
		this.availabilityActivitiesIds = $A();
		this.indexes = new Hash;
        this.vendors = new Hash;
    },
    getIndex: function(alias) {
		return this.indexes.get(alias) || new Array;
    },
	setIndex: function(alias, data) {
		this.indexes.set(alias, data);
	},
    setActivities: function(hash) {
        this.activities = hash;
    },
    addAvailableActivityId: function(activityId) {
        if (!this.availabilityActivitiesIds.include(activityId)) {
            this.availabilityActivitiesIds.push(activityId);
        }
    },
    setVendors: function(vendors) {
        this.vendors = vendors;
        this._setNotDirectVendors();
    },
    getVendors: function() {
        return this.vendors;
    },
    getVendorById: function(vendorId) {
        return this.getVendors().find(function(vendor) { return vendor.id == vendorId });
    },
    isDirectVendor: function(vendorId) {
        return !this.notDirectVendors.include(vendorId);
    },
    isCommercialVendor: function(vendorId) {
        return this.notDirectVendors.include(vendorId) && vendorId != 71;
    },
    _setNotDirectVendors: function() {
        this.notDirectVendors = this.getVendors().collect(
            function(vendor) { return vendor.id }
        );
    }, 
    _rebuildIndex: function(alias, activityId) {
		console.log('AttractionsStorage::_rebuildIndex');
        try {
        products = $A(this.getData()).partition(function(item) { 
            return this.isDirectVendor(item.vendorId); 
        }, this);
        directProducts = products[0];
        
        notDirectProducts = products[1].partition(function(item) { 
            return this.isCommercialVendor(item.vendorId); 
        }, this);
        
        commercialProducts = notDirectProducts[0]; 
        notCommercialProducts = notDirectProducts[1]; 
        
        getItemId = function(item) { return item.id };
        
        if (activityId) {
            checkActivity = function(item) { 
                return item.activities.include(activityId);
            }; 
        } else {
            checkActivity = function(item) { return true; };
        }
		switch (alias) {
			case 'name':
                comTmp = directProducts.concat(commercialProducts)
                                       .findAll(checkActivity)
                                       .sortBy(function(item) { return item.name; })
                                       .collect(getItemId);
                notComTmp = notCommercialProducts.findAll(checkActivity)
                                                 .sortBy(function(item) { return item.name; })
                                                 .collect(getItemId);
                tmp = comTmp.concat(notComTmp);
                this.setIndex(activityId + '_name_asc', tmp);
                
                tmp = comTmp.reverse(false).concat(notComTmp.reverse(false));
                this.setIndex(activityId +'_name_desc', tmp);
				break;
			case 'price':
                comTmp = directProducts.concat(commercialProducts)
                                       .findAll(checkActivity)
                                       .sortBy(function(item) { return Number(item.price) })
                                       .collect(getItemId);
                notComTmp = notCommercialProducts.findAll(checkActivity)
                                                 .sortBy(function(item) { return Number(item.price) })
                                                 .collect(getItemId);
                tmp = comTmp.concat(notComTmp);
				this.setIndex(activityId + '_price_asc', tmp);
                
                tmp = comTmp.reverse(false).concat(notComTmp.reverse(false));
				this.setIndex(activityId + '_price_desc', tmp);
				break;
            case 'default':
                directIndex = directProducts.findAll(checkActivity).collect(getItemId);
                commercialIndex = commercialProducts.findAll(checkActivity).collect(getItemId);
                notCommercialIndex = notCommercialProducts.findAll(checkActivity).collect(getItemId);
                tmp = directIndex.concat(commercialIndex).concat(notCommercialIndex);
            
                this.setIndex(activityId + '_default_none', tmp);
                break;
			default:
				// no default action
				break;
		}
        } catch (e) { console.log(e) }
    },
	_lock: function() {
		console.log('AttractionsStorage::lock');
		this.isLocked = true;
		return this;
	},
	_unlock: function() {
		console.log('AttractionsStorage::unlock');
		this.isLocked = false;
		return this;
	},
	isLocked: function() {
		return this.isLocked;
	},
	update: function(data) {
		console.log('AttractionsStorage::rebuild');
		this._lock();
		this.setData(data);
		
		$A(this.getData()).each(function(item, index) {
            item.id = index;
            $A(item.activities).each(function(activityId) {
                this.addAvailableActivityId(activityId);
            }, this); 
        }, this);

        this._rebuildIndex('default', 0);
        this._rebuildIndex('name', 0);
        this._rebuildIndex('price', 0);
        
        this.availabilityActivitiesIds.each(function(activityId) {
            this._rebuildIndex('default', activityId);
            this._rebuildIndex('name', activityId);
            this._rebuildIndex('price', activityId);
        }, this);
		
		this._unlock();
		return this;
	},
	getData: function() {
		return this.data;
	},
	setData: function(data) {
        $A(data).each(function(item) {
            this.data.push(item);
        }, this);
	},
	getItemById: function(id) {
		return this.data.find(function(item) { return item.id == Number(id); });
	}	
});
