/**
* Created by Chantell.Nichols on 10/8/2015.
*/
define(['_', 'promise', './../util/util'], function (_, Promise, util) {
var PlaceData = {};
var setPlaceStatus = function (place, type) {
switch (type) {
case 'resale':
place.status = 'RESALE';
break;
case 'primary':
place.status = 'OPEN';
break;
default:
place.status = 'SOLD';
break;
}
};
var setPlaceOffer = function setPlaceOffer(place, offer) {
place.offerIds = place.offerIds || [];
var elementIndex = place.offerIds.indexOf(offer.offerId);
if (elementIndex === -1) {
place.offerIds.push(offer.offerId);
place.offers = place.offers || [];
place.offers.push(offer);
}
};
var setPlaceOffers = function (offer, placeIds, places) {
var index,
length = placeIds.length;
for (index = 0; index < length; index++) {
var placeId = placeIds[index];
var place = _.find(places, 'id', placeId);
if (place) {
setPlaceOffer(place, offer);
// This will handle undefined
if (_.every(place.offers, 'protected', true)) {
place.isProtected = _.isEmpty(_.intersection(place.offerIds, PlaceData.unlockedOfferIds));
} else {
place.isProtected = false;
}
}
}
};
var fetchPlaceOffers = function (plugin, offerData, places) {
var offerIds = Object.keys(offerData),
neededOffers = [],
getOffers = plugin.urlBuilder.getOffers;
var index,
length = offerIds.length;
for (index = 0; index < length; index++) {
var offerId = offerIds[index];
var offer = plugin.offers[offerId];
if (!offer) {
neededOffers.push(offerId)
} else {
setPlaceOffers(offer, offerData[offerId], places);
}
}
var promises = [];
for (index = 0; index < neededOffers.length; index++) {
promises.push(getOffers(neededOffers[index]));
}
if (promises.length) {
return Promise.all(promises)
.then(function (offers) {
offers.forEach(function (offer) {
plugin.offers[offer.offerId] = offer;
setPlaceOffers(offer, offerData[offer.offerId], places);
});
});
} else {
return Promise.resolve();
}
};
var parseOffers = function (placeId, offerIds, placeOfferData) {
var index, length = offerIds.length;
for (index = 0; index < length; index++) {
var offerId = offerIds[index];
var places = placeOfferData[offerId] || [];
places.push(placeId);
placeOfferData[offerId] = places;
}
return placeOfferData;
};
var setPlaceAttributes = function (plugin, place, facet, placeOfferData) {
var type = facet.inventoryTypes[0];
setPlaceStatus(place, type);
return parseOffers(place.id, facet.offers, placeOfferData);
};
var unSetPlaceStatus = function (core, places, placeIds) {
var index,
length = placeIds.length;
for (index = 0; index < length; index++) {
var placeId = placeIds[index];
var place = _.find(places, 'id', placeId);
setPlaceStatus(place, 'SOLD');
}
};
var parsePlaceDataBySegment = function (plugin, facet, places, usedPlaces, placeOfferData) {
var index,
length = facet.length;
for (index = 0; index < length; index++) {
var placeIndex, data = facet[index],
placeIds = data.places;
for (adaPlaceIndex = 0; adaPlaceIndex < placeIds.length; adaPlaceIndex++) {
var placeId = placeIds[adaPlaceIndex];
var place = _.find(places, 'id', placeId);
if (place) {
usedPlaces.push(placeId);
setPlaceAttributes(plugin, place, data, placeOfferData);
}
}
}
return placeOfferData;
};
var parsePlaceData = function (plugin, facets, places) {
var index,
usedPlaces = [],
core = plugin.core,
keys = Object.keys(facets),
placeOfferData = plugin._placeOfferData,
length = keys.length;
for (index = 0; index < length; index++) {
var segmentId = keys[index];
var facet = facets[segmentId];
parsePlaceDataBySegment(plugin, facet, places, usedPlaces, placeOfferData);
}
var allPlaces = util.pluck(places, 'id');
var untouchedPlaces = _.difference(allPlaces, usedPlaces);
if (untouchedPlaces.length) {
unSetPlaceStatus(core, places, untouchedPlaces);
}
return fetchPlaceOffers(plugin, placeOfferData, places);
};
var getNeededSegments = function getNeededSegments(core, segmentIds, placeUpdateInterval) {
var index, length = segmentIds.length,
neededSegments = [],
time = performance.now();
for (index = 0; index < length; index++) {
var segmentId = segmentIds[index];
var segment = core.data.segmentsById[segmentId];
if (segment.timeStamp < Math.abs(time - placeUpdateInterval)) {
neededSegments.push(segmentId);
segment.timeStamp = time;
}
}
return neededSegments;
};
var appendArray = function appendArray(first, second) {
var index = 0,
length = second.length,
element;
while (index < length) {
element = second[index];
first.push(element);
index++;
}
};
var getPlaces = function getPlaces(segments) {
var places = [],
index, length = segments.length;
for (index = 0; index < length; index++) {
var segment = segments[index];
if (segment.segments.length) {
appendArray(places, getPlaces(segment.segments));
}
appendArray(places, segment.places);
}
return places;
};
var unlockPlaces = function unlockPlaces(plugin, placeIds) {
var places = plugin.core.data.placesById,
place, placeId,
index, length;
placeIds = placeIds || [];
length = placeIds.length;
for (index = 0; index < length; ++index) {
placeId = placeIds[index];
place = places[placeId];
if (place) {
place.isProtected = false;
}
}
};
var unlockPlacesForOffers = function unlockPlacesForOffers(plugin, offerIds) {
var offerMap = plugin._placeOfferData,
offerId,
placeIds,
length = offerIds.length,
index;
for (index = 0; index < length; ++index) {
offerId = offerIds[index];
placeIds = offerMap[offerId];
unlockPlaces(plugin, placeIds);
}
};
PlaceData.init = function (core) {
this.unlockedOfferIds = [];
this.unlockedOfferIdsByPass = {};
core.Place.addPluginProperty('ada', false, true);
core.Place.addPluginProperty('status', 'SOLD', true);
core.Place.addPluginProperty('offers', null, false);
core.Place.addPluginProperty('isProtected', false, true);
core.Segment.addPluginProperty('timeStamp', 0, false);
};
PlaceData.getPlaceData = function (plugin, segments, placeUpdateInterval) {
var getPlaceData = plugin.urlBuilder.getPlaceData,
segments = segments || [],
core = plugin.core;
var segmentIds = getNeededSegments(core, segments, placeUpdateInterval);
if (segmentIds.length === 0) {
return Promise.resolve();
}
core.emit('place-availability-update-started');
core.startLoading();
var promises = [
core.data.requestSegments(segmentIds),
getPlaceData(segmentIds, plugin.resaleEnabled, plugin.platinumEnabled)
];
return Promise.all(promises)
.then(function (results) {
var segments = results[0];
var data = results[1];
if (!data.facets.length) {
core.emit('place-availability-update-complete');
core.finishLoading();
return Promise.resolve();
}
var allPlaces = getPlaces(segments);
return parsePlaceData(plugin, _.groupBy(data.facets, 'shapes'), allPlaces)
.then(function () {
core.emit('place-availability-update-complete');
core.finishLoading();
});
})
};
PlaceData.fetchPlaceData = function (plugin, segmentIds, placeUpdateInterval) {
var self = this;
var core = plugin.core;
return this.getPlaceData(plugin, segmentIds, placeUpdateInterval)
.then(function () {
return Promise.delay(placeUpdateInterval)
})
.then(function () {
return self.getPlaceData(plugin, core.map.renderedSections, placeUpdateInterval);
});
};
PlaceData.unlockOffers = function (plugin, password, newUnlockedOfferIds) {
this.unlockedOfferIdsByPass[password] = newUnlockedOfferIds;
this.unlockedOfferIds = _(this.unlockedOfferIdsByPass).values().flatten().union().value();
unlockPlacesForOffers(plugin, newUnlockedOfferIds);
};
return PlaceData;
});