<?php

/**
 * AdGallery
 *
 * Uses ad-gallery from here http://coffeescripter.com/code/ad-gallery/
 * Makes a gallery for you that displays several images
 *
 * Example Usage: (Please note, all config options are optional, only a list of images is necessary)
 * 	$this->widget('ext.adGallery.AdGallery',
 *			array(
 *				'imageList' => array(
 *					array(
 *						'image_url' => 'images/1.jpg',
 *						'thumb_url' => 'images/thumbs/t1.jpg',
 *						'title' => 'Test tile',
 *						'link' => 'http://www.google.com/',
 *						'alt' => 'Something something',
 *					),
 *					array(
 *						'image_url' => 'images/2.jpg',
 *						'title' => 'Test tile sdfjaskdf',
 *						'link' => 'http://www.msn.com/',
 *					),
 *					'images/3.jpg',
 *					'images/4.jpg',
 *					'images/5.jpg',
 *					'images/6.jpg',
 *					'images/7.jpg',
 *					'images/8.jpg',
 *					'images/9.jpg',
 *					'images/10.jpg',
 *					'images/11.jpg',
 *					'images/12.jpg',
 *				),
 *			)
 *		);
 *
 * @author Corey Tisdale
 * @copyright Copyright &copy; 2010
 *
 */

class AdGallery extends CWidget
{
	/****** widget options ******/

	/**
	 * @boolean whether or not to show the widget
	 */
	public $visible				= true;

	/**
	 * @string the url of a css file to load instead of the default
	 */
	public $cssFile				= null;

	/**
	 * @string the css class of the container div
	 */
	public $cssClass			= 'adGallery';

	/**
	 * @string the css id of the container div
	 */
	public $cssId				= null; //will be automatically set if not provided

	/**
	 * @array the list of images to render. Can be in one of
	 * two formats (you can mix formats in one array):
	 *
	 * Simple:
	 * array(
	 *	  'image/url/1.jpg',
	 *	  'image/url/2.jpg',
	 * )
	 *
	 * or
	 *
	 * Detailed:
	 * array(
	 *	  array(
	 *		'thumb_url' => 'image/thumb/1.jpg', //optional, smaller thumb to load before big image
	 *		'image_url' => 'image/big/1.jpg',
	 *		'title' => 'Some title here', //optional, will display on top of big image
	 *		'link' => 'http://my.place.com/link', //optional, will go here when big image clicked on
	 *	  ),
	 *	  array(
	 *		'thumb_url' => 'image/thumb/2.jpg', //optional, smaller thumb to load before big image
	 *		'image_url' => 'image/big/2.jpg',
	 *		'title' => 'Some other title here', //optional, will display on top of big image
	 *		'link' => 'http://my.place.com/link2', //optional, will go here when big image clicked on
	 *	  ),
	 * )
	 */
	public $imageList			= array();

	/******* widget private vars *******/
	private $baseUrl			= null;
	private $defaultCssFile		= '/jquery.ad-gallery/jquery.ad-gallery.css'; //Only used if $cssFile is null (if css file was not overriden by user)
	private $jsFiles			= array(
			'/jquery.ad-gallery/jquery.ad-gallery.pack.js',
	);

	/******* ad-gallery Options *******/
	/**
	 * @string the url of the image to use when images are loading
	 */
	public $agLoaderImage					= '/jquery.ad-gallery/loader.gif'; //Not customizable at the moment, could be soon

	/**
	 * @integer the width of the gallery big image in pixels
	 */
	public $agWidth							= 450;

	/**
	 * @integer the height of the gallery big image in pixels
	 */
	public $agHeight						= 300;

	/**
	 * @integer the width of the gallery thumb image in pixels. Null means use actual image size
	 */
	public $agThumbWidth					= null;

	/**
	 * @integer the height of the gallery thumb image in pixels. Null means use actual image size
	 */
	public $agThumbHeight					= 75;

	/**
	 * @float A value between 0 and 1 that dictates how opaque thumbnails will be. 1 removes fade effect
	 */
	public $agThumbOpacity					= 0.7; // Opacity that the thumbs fades to/from, (1 removes fade effect)

	/**
	 * @integer the index of the gallery images to start at
	 */
	public $agStartAtIndex					= 0; // Which image should be displayed at first? 0 is the first image

	/**
	 * @string Either false for default positioning or a jQuery object representing where to put the description
	 */
	public $agDescriptionWrapper			= 'false'; // Either false (string value 'false', not boolean false)or a jQuery object, if you want the image descriptions	to be placed somewhere else than on top of the image

	/**
	 * @string String values 'true' or 'false' (not boolean true or false). Determinse whether or not to animate in first image
	 */
	public $agAnimateFirstImage				= 'false'; // Should first image just be displayed, or animated in?

	/**
	 * @integer the animation speed for the effects between images
	 */
	public $agAnimationSpeed				= 400; // Which ever effect is used to switch images, how long should it take?

	/**
	 * @string String values 'true' or 'false' (not boolean true or false). Whether or not to allow navigation by clicking the sides of the image
	 */
	private $agDisplayNextAndPrev			= 'true'; // Can you navigate by clicking on the left/right on the image?

	/**
	 * @string String values 'true' or 'false' (not boolean true or false) If you are allowed to scroll through the thumb list
	 */
	public $agDisplayBackAndForward			= 'true'; // Are you allowed to scroll the thumb list?

	/**
	 * @integer How many images to scroll at a time. If 0, it jumps the width of the container
	 */
	public $agScrollJump					= 0; // If 0, it jumps the width of the container

	/**
	 * @string String values 'true' or 'false' (not boolean true or false). Whether or not to enable the slide show
	 */
	public $agSlideShowEnable				= 'true';

	/**
	 * @string String values 'true' or 'false' (not boolean true or false) Whether to auto start slideshow
	 */
	public $agSlideShowAutoStart			= 'false';

	/**
	 * @integer the speed in miliseconds between slides in the slideshow
	 */
	public $agSlideShowSpeed				= 5000;

	/**
	 * @string The label for the link to start the slideshow
	 */
	public $agSlideShowStartLabel			= 'Start';

	/**
	 * @string String The label for the link to stop the slideshow
	 */
	public $agSlideShowStopLabel			= 'Stop';

	/**
	 * @string String values 'true' or 'false' (not boolean true or false) Whether or not to stop the slideshow on scroll
	 */
	public $agSlideShowStopOnScroll			= 'true';

	/**
	 * @string The prefix for the countdown timer
	 */
	public $agSlideShowCountdownPrefix		= '(';

	/**
	 * @string The suffix for the countdown timer
	 */
	public $agSlideShowCountdownSuffix		= ')';

	/**
	 * @string The callback function for the slideshow start
	 */
	public $agSlideShowOnStart				= null;

	/**
	 * @string The callback function for the slideshow stop
	 */
	public $agSlideShowOnStop				= null;

	/**
	 * @string The effect for changing images. Can be 'slide-hori' or 'slide-vert', 'resize', 'fade', 'none' or false
	 */
	public $agEffect						= 'fade'; //'slide-hori' or 'slide-vert', 'resize', 'fade', 'none' or false

	/**
	 * @string String values 'true' or 'false' (not boolean true or false) Whether to move between images with the keyboard
	 */
	public $agEnableKeyboardMove			= 'false'; // Move to next/previous image with keyboard arrows?

	/**
	 * @string String values 'true' or 'false' (not boolean true or false) Whether you can go from the last image to the first and visa versa
	 */
	public $agCycle							= 'true'; // If set to false, you can't go from the last image to the first, and vice versa

	/**
	 * @string The javascript callback function for the init event of the gallery
	 */
	public $agCallbacksInit					= null;

	/**
	 * @string The javascript callback function for before each image is visible
	 */
	public $agCallbacksBeforeImageVisible	= null;

	/**
	 * @string The javascript callback function for after each image is visible
	 */
	public $agCallbacksAfterImageVisible	= null;

	/**
	 * Initialize the widget
	 */
	public function init()
	{
		// Don't do anything if I'm not visible
		if(!$this->visible) {
			return;
		}

		//If we have no images, just don't do anything
		if( !is_array($this->imageList) || count($this->imageList) === 0 ) {
			$this->visible = false;
			return;
		}

		//Set css Id
		if(is_null($this->cssId))
			$this->cssId = 'adGallery' . $this->getId();

		//Publish assets
		$this->publishAssets();
		$this->registerCSSFiles();
		$this->registerClientScripts();

		parent::init();
	}


	/**
	 * Publishes the assets
	 */
	public function publishAssets()
	{
		$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets';
		$this->baseUrl = Yii::app()->getAssetManager()->publish($dir);
	}

	/**
	 * Registers the external javascript files
	 */
	public function registerClientScripts()
	{
		// add the css
		if ($this->baseUrl === '')
			throw new CException(Yii::t('AdGallery', 'baseUrl must be set. This is done automatically by calling publishAssets()'));

		// add the core script
		$cs = Yii::app()->getClientScript();
		$cs->registerCoreScript('jquery');

		//Register the main script files
		foreach($this->jsFiles as $jsFile) {
			$galleryJsFile = $this->baseUrl . $jsFile;
			$cs->registerScriptFile($galleryJsFile, CClientScript::POS_HEAD);
		}

		//Register the widget-specific script on ready
		$js = $this->generateOnloadJavascript();
		$cs->registerScript('adGallery'.$this->getId(), $js, CClientScript::POS_READY);
	}

	protected function generateOnloadJavascript() {
		//Gallery javascript
		$js = "\$('#{$this->cssId}').adGallery({
		loader_image: '{$this->baseUrl}{$this->agLoaderImage}',
		width: {$this->agWidth},
		height: {$this->agHeight},
		thumb_opacity: {$this->agThumbOpacity},
		start_at_index: {$this->agStartAtIndex},
		description_wrapper: {$this->agDescriptionWrapper},
		animate_first_image: {$this->agAnimateFirstImage},
		animation_speed: {$this->agAnimationSpeed},
		display_next_and_prev: {$this->agDisplayNextAndPrev},
		display_back_and_forward: {$this->agDisplayBackAndForward},
		scroll_jump: {$this->agScrollJump},
		slideshow: {
		enable: {$this->agSlideShowEnable},
		autostart: {$this->agSlideShowAutoStart},
		speed: {$this->agSlideShowSpeed},
		start_label: '{$this->agSlideShowStartLabel}',
		stop_label: '{$this->agSlideShowStopLabel}',
		stop_on_scroll: {$this->agSlideShowStopOnScroll},
		countdown_prefix: '{$this->agSlideShowCountdownPrefix}',
		countdown_sufix: '{$this->agSlideShowCountdownSuffix}',\n";
			
		if(!is_null($this->agSlideShowOnStart))
			$js .= "onStart: {$this->agSlideShowOnStart},\n";

		if(!is_null($this->agSlideShowOnStop))
			$js .= "onStop: {$this->agSlideShowOnStop},\n";

		$js .= "},
		effect: '{$this->agEffect}',
		enable_keyboard_move: {$this->agEnableKeyboardMove},
		cycle: {$this->agCycle},
		callbacks: {\n";

		if(!is_null($this->agCallbacksInit))
			$js .= "init: {$this->agCallbacksInit},\n";

		if(!is_null($this->agCallbacksAfterImageVisible))
			$js .= "afterImageVisible: {$this->agCallbacksAfterImageVisible},\n";

		if(!is_null($this->agCallbacksBeforeImageVisible))
			$js .= "beforeImageVisible: {$this->agCallbacksBeforeImageVisible},\n";

		$js .= "}
	});";
			
		if(!is_null($this->agThumbHeight) || !is_null($this->agThumbWidth)) { //Only set the thumb size if they are overridden, otherwise let them be whatever
			$js .= " \$('#{$this->cssId} .ad-thumbs img').each(function(index) { ";

			if( !is_null($this->agThumbHeight) )
				$js .= " \$(this).height({$this->agThumbHeight}); ";

			if( !is_null($this->agThumbWidth) )
				$js .= " \$(this).height({$this->agThumbWidth}); ";

			$js .= " }); ";
		}

		$js .= " \$('#{$this->cssId} .ad-thumbs').each(function(index) { \$(this).height(\$('#{$this->cssId} .ad-thumbs img').outerHeight(true)); }); "; //Sometimes the image thumb container load funny
		$js .= " \$('#{$this->cssId} .ad-gallery').each(function(index) { $(this).width({$this->agWidth}); }); "; //Takes care of the height in Chrome
		$js .= " \$('#{$this->cssId} .ad-image-wrapper').each(function(index) { $(this).width({$this->agWidth}); }); "; //Heard from community ad-image-wrapper should be larger as well

		return $js;
	}

	/**
	 * Registers the external CSS files
	 */
	public function registerCssFiles()
	{
		if ($this->baseUrl === '')
			throw new CException(Yii::t('AdGallery', 'baseUrl must be set. This is done automatically by calling publishAssets()'));

		$cs=Yii::app()->getClientScript();

		//Register the user's css if it was set, or the default if it was not
		if(is_null($this->cssFile))
			$url=$this->baseUrl.$this->defaultCssFile;
		else
			$url = $this->cssFile;

		$cs->registerCssFile($url,'screen, projector');
	}

	/**
	 * Run the widget
	 */
	public function run()
	{
		if(!$this->visible)
			return

			//Render AdGallery template
		$this->getViewFile('adGallery'); //Why do I have to do this? Unkown but rendering the file doesn't work unless I call this
		$this->render('adGallery',
				array(
						'imageList' => $this->imageList
				)
		);
		parent::run();
	}
}