/**

 * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing

 * markers' icon options and refreshing their icon and their parent clusters

 * accordingly (case where their iconCreateFunction uses data of childMarkers

 * to make up the cluster icon).

 */





L.MarkerClusterGroup.include({

	/**

	 * Updates the icon of all clusters which are parents of the given marker(s).

	 * In singleMarkerMode, also updates the given marker(s) icon.

	 * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)|

	 * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent

	 * clusters need to be updated. If not provided, retrieves all child markers of this.

	 * @returns {L.MarkerClusterGroup}

	 */

	refreshClusters: function (layers) {

		if (!layers) {

			layers = this._topClusterLevel.getAllChildMarkers();

		} else if (layers instanceof L.MarkerClusterGroup) {

			layers = layers._topClusterLevel.getAllChildMarkers();

		} else if (layers instanceof L.LayerGroup) {

			layers = layers._layers;

		} else if (layers instanceof L.MarkerCluster) {

			layers = layers.getAllChildMarkers();

		} else if (layers instanceof L.Marker) {

			layers = [layers];

		} // else: must be an Array(L.Marker)|Map(L.Marker)

		this._flagParentsIconsNeedUpdate(layers);

		this._refreshClustersIcons();



		// In case of singleMarkerMode, also re-draw the markers.

		if (this.options.singleMarkerMode) {

			this._refreshSingleMarkerModeMarkers(layers);

		}



		return this;

	},



	/**

	 * Simply flags all parent clusters of the given markers as having a "dirty" icon.

	 * @param layers Array(L.Marker)|Map(L.Marker) list of markers.

	 * @private

	 */

	_flagParentsIconsNeedUpdate: function (layers) {

		var id, parent;



		// Assumes layers is an Array or an Object whose prototype is non-enumerable.

		for (id in layers) {

			// Flag parent clusters' icon as "dirty", all the way up.

			// Dumb process that flags multiple times upper parents, but still

			// much more efficient than trying to be smart and make short lists,

			// at least in the case of a hierarchy following a power law:

			// http://jsperf.com/flag-nodes-in-power-hierarchy/2

			parent = layers[id].__parent;

			while (parent) {

				parent._iconNeedsUpdate = true;

				parent = parent.__parent;

			}

		}

	},



	/**

	 * Re-draws the icon of the supplied markers.

	 * To be used in singleMarkerMode only.

	 * @param layers Array(L.Marker)|Map(L.Marker) list of markers.

	 * @private

	 */

	_refreshSingleMarkerModeMarkers: function (layers) {

		var id, layer;



		for (id in layers) {

			layer = layers[id];



			// Make sure we do not override markers that do not belong to THIS group.

			if (this.hasLayer(layer)) {

				// Need to re-create the icon first, then re-draw the marker.

				layer.setIcon(this._overrideMarkerIcon(layer));

			}

		}

	}

});



L.Marker.include({

	/**

	 * Updates the given options in the marker's icon and refreshes the marker.

	 * @param options map object of icon options.

	 * @param directlyRefreshClusters boolean (optional) true to trigger

	 * MCG.refreshClustersOf() right away with this single marker.

	 * @returns {L.Marker}

	 */

	refreshIconOptions: function (options, directlyRefreshClusters) {

		var icon = this.options.icon;



		L.setOptions(icon, options);



		this.setIcon(icon);



		// Shortcut to refresh the associated MCG clusters right away.

		// To be used when refreshing a single marker.

		// Otherwise, better use MCG.refreshClusters() once at the end with

		// the list of modified markers.

		if (directlyRefreshClusters && this.__parent) {

			this.__parent._group.refreshClusters(this);

		}



		return this;

	}

});

