/**
 * Create a flash coverflow effect to display images.
 *
 * The `.uiCoverflow()` method creates a flash object to display the given images.
 *
 * The classes BorderColor0x000000,MainColorAlt0x000000 and
 * MainColor0x000000 define how the created coverflow will look like.
 * title and title2 define how the to action links of the coverflow are named.
 * The first action link takes the src from the a tag of every image in the collection as target.
 * The second link only workes inside ePages and uses the addToBasket method of this widget.
 *
 * You can create a coverflow with the optional parameter imagesData and pass the images data in an array to
 * the widget like:
 *
 * ### Examples
 * Apply .uiCoverflow() to collection of images.
 *
 * JavaScript:
 *
 *     ep('.CoverFlow')
 *         .uiCoverflow({});
 *
 * HTML:
 *
 *     <div class="CoverFlow BorderColor0x333333 MainColorAlt0x000000 MainColor0x000000 HideElement" title="Coverflow" title2="title2">
 *       <a href="http://www.epages.de">
 *         <img src="ep/ui/CoverflowTest_image.jpg"
 *              longdesc="longDescription"
 *         />
 *       </a>
 *       <a href="http://www.epages.de">
 *        <img src="ep/ui/CoverflowTest_image.jpg"
 *             longdesc="longDescription"
 *        />
 *       </a>
 *     </div>
 *
 * Apply .uiCoverflow() to a domnode and add images directly via parameter.
 *
 * JavaScript:
 *
 *     ep('.CoverFlow')
 *         .uiCoverflow({
 *           imagesData: [
 *           {
 *             medium: 'imageA.png',
 *             desciption:'a beautiful image'
 *           },
 *           {
 *             medium: 'imageB.png',
 *             desciption:'a beautiful image'
 *           }
 *           ]
 *         });
 *
 * HTML:
 *
 *     <div class="CoverFlow BorderColor0x333333 MainColorAlt0x000000 MainColor0x000000 HideElement" title="Coverflow" title2="title2">
 *     </div>
 *
 *
 * @class jQuery.ui.uiCoverflow
 * @extends jQuery.widget
 *
 * @uses ep
 * @uses jQuery.ui.widget
 * @uses jQuery.support.flash
 * @uses jQuery.compareVersion
 * @since 6.11.1
 */

/**
 * @cfg {Array} [imagesData] an array of hashes with the data of the images to display
 */

/**
 * See `jQuery.ui.uiCoverflow` for details.
 *
 * @param {Object} [options] A map of additional options pass to the method.
 * @param {Array} [imagesData] an array of hashes with the data of the images to display
 *
 * @method uiCoverflow
 * @member jQuery
 *
 * @since 6.11.1
 */

/*
 * @copyright       © Copyright 2006-2010, epages GmbH, All Rights Reserved.
 *
 * @module          ep.ui.coverflow
 *
 * @revision        $Revision: 1.15 $
 */

define("ep/ui/coverflow", [
    "jquery",
    "ep",
    "util/string",
    "util/support",
    "util/version",

    "util/browser",
    "jquery/cookie",
    "jquery/ui/widget",
    "ep/ui/core",
    "ep/ui/slides"
], function ($, ep, str, support, version) {

	var shift = Array.prototype.shift,

		swf = location.protocol + '//' + location.host + ep.config.javascriptRoot + '/ep/ui/coverflow.swf',

		uid = 0,

		bridge = function (self) {
			return (bridge[self.id] = {
				// get flash optimized data of images
				/**
				 * returns the data of the images which will be displayed inside the coverflow. This method is called by
				 * the flash object.
				 *
				 * @method getData
				 * @member jQuery.ui.uiCoverflow
				 *
				 * @since 6.11.1
				 */
				getData: function () {
					var result = [],
						caption = self.options.caption;

					self.images.each(function (i, item) {
						result.push([
                            item.srcM, // medium image source
                            caption && item.desc ? str.shrink(item.desc.replace(/\n/g, " "), {
								length: 40,
								ratio: 0.5
							}) : "", // image description
                            "showProduct", // click display action
                            "addToBasket", // click add to basket action
                            false, // is map
                            i // stack index number
                        ]);
					});

					return result;
				},
				// handle change event trigegr by flash
				change: function (i) {
					self.images.current(i);
				},
				// trigger show product action
				showProduct: function (i) {
					if (self.options.action) {
						self.images.trigger(self.options.action);
					}
				},
				//#JSCOVERAGE_IF false
				// trigger add to basket action
				/**
				 * this method is a connector method for the flash object and adds the current selected product to the basket.
				 * method only works inside epages and with valid product data.
				 *
				 * @method addToBasket
				 * @member jQuery.ui.uiCoverflow
				 *
				 * @since 6.11.1
				 */
				addToBasket: function (i) {
					var node = self.images.current().node,
						addToBasketLink,
						tokenName = "SecToken",
						cookies = $.cookie();

					if (node) {
						addToBasketLink = $(node).closest("a").data("addToBasket");
						if (addToBasketLink) {
							// check if security token exists and add security cookie information
							if (cookies[tokenName]) {
								addToBasketLink += "&" + tokenName + "=" + cookies[tokenName];
							}

							$.ajax({
								type: 'POST',
								url: addToBasketLink,
								async: false
							})
								.done(function () {
									window.location.href = location.protocol.toLowerCase() == "https:" ?
										ep.config.webUrlSsl :
										ep.config.webUrl;
								});
						}
					}
				}
				//#JSCOVERAGE_ENDIF
			});
		};

	$.widget('ui.uiCoverflow', {

		options: {
			//  action      : "slideshow",  // example: 'slideshow' / 'location'
			title: "",
			images: "img",
			caption: false,

			count: false, // only for alternative/fallback html version
			autoplay: true, // only for alternative/fallback html version
			controls: true, // only for alternative/fallback html version
			delay: 3000 // only for alternative/fallback html version
		},

		_create: function () {
			var self = this,
				o = self.options,
				imgs = self.images = ep.ui.imgData(o.images)
				.on("change.uiCoverflow", $.proxy(self, "_change"));

			// provide swf connection
			self.id = "cwf" + $.now() + "" + (++uid);
			bridge(self);

			// set title
			o.title = o.title || self.element.attr("title") || "";

			// check flash vs. alternative
			if (version.compare(support.flash, '9') >= 0 && imgs.length > 2) {
				self.flash = $();
				self._buildFlash();
				self.element.addClass('Flashed')
					.removeClass('HideElement');
				$(window)
					.on('resize', $.proxy(self, '_buildFlash'));
			} else {
				self._buildHTML();
			}
		},

		_change: function () {
			var self = this;

			if (self.flash && self.flash[0] && self.flash[0].setCurrent) {
				self.flash[0].setCurrent(self.images.currentItem);
			}
		},

		_buildHTML: function () {
			var self = this,
				o = self.options;

			self.element
				.removeClass('HideElement')
				.uiSlides(o)
				.children('a')
				.hide();
		},

		_buildFlash: function () {
			var self = this,
				//random string is necessary to avoid that the IE thinks he had not to render the flash again
				movie = $.browser.msie && parseInt($.browser.version) <= 8 ?
				swf + "?" + $.now() + (++uid) :
				swf;
			// flash object html string
			flash = '<object ' +
				'name="' + self.id + '" ' +
				'id="' + self.id + '" ' +
				'type="application/x-shockwave-flash" ' +
				'data="' + movie + '" ' +
				'data-jsapi="jQuery.ui.uiCoverflow.flash" ' +
				'data-jscallback="getData" ' +
				'data-jschange="change" ' +
				'><param ' +
				'name="movie" ' +
				'value="' + movie + '" ' +
				'/><param ' +
				'name="allowscriptaccess" ' +
				'value="always"' +
				'/><param ' +
				'name="wmode" ' +
				'value="transparent" ' +
				'/><param ' +
				'name="swliveconnect" ' +
				'value="true" ' +
				'/></object>';

			// clear existing in DOM
			if (self.flash) {
				self.flash.remove();
			}
			// add to DOM
			self.flash = self.element
				.attr('title', self.options.title)
				.append(flash)
				.find('object');
		},

		destroy: function () {
			this._superApply(arguments);
		}

	});

	// external public connetion for swf/flash actions
	$.extend($.ui.uiCoverflow, {
		flash: function () {
			return bridge[shift.call(arguments)][shift.call(arguments)].apply(bridge, arguments);
		}
	});

	return ep;

});