function DollyShot(target) {
	var _ds = this;
	_ds.target = target;
	_ds.params = MyLib.getParams(
		target[0],
		['tissueOpacity', 'tissueTop', 'tissueAnimDuration', 'speed', 'stepTime'],
		{ tissueOpacity: 0.8, tissueTop: 180, tissueAnimDuration: 600, speed: 40, stepTime: 10 }
	);
	
	_ds.cards = [];
	_ds.content = _ds.target.find('.js-dollyShot-content');
	_ds.target.find('.js-dollyShot-content > .js-dollyShot-item').each(function() {
		var cardDom = $(this);
		var imageDom = $(this).find('img');
		var marginleft = parseInt(imageDom.css('margin-left').replace('px',''));
		var marginRight = parseInt(imageDom.css('margin-right').replace('px',''));
		var curtainDom = cardDom.find('div').first();
		curtainDom.hide();
		var card = {
			'cardDom': cardDom.detach(),
			'visible': false,
			'imageDom': imageDom,
			'curtainDom': curtainDom,
			'marginleft': marginleft,
			'marginRight': marginRight,
			'tissueOpacity': _ds.params.tissueOpacity,
			'tissueTop': _ds.params.tissueTop
		};
		_ds.cards.push(card);
	});
	MyLib.shuffleArray(this.cards);
	_ds.leftX = 0;
}
DollyShot.prototype.init = function() {
	var _ds = this;

	_ds.toBeStarted = false;
	_ds.imagesToLoad = _ds.cards.length;
	for (var i = 0; i < _ds.cards.length; i++) {
		var card = _ds.cards[i];
		var image = card.imageDom[0];
		var localImage = new Image();
		localImage._card = card;
		$(localImage).load(function() {
			this._card.imageWidth = this.width;
			this._card.imageHeight = this.height;
			_ds.imagesToLoad--;
			if (_ds.imagesToLoad <= 0) {
				_ds.placeImages();
				if (_ds.toBeStarted) {
					_ds.start();
				}
			}
		});
		localImage.src = image.src;
	}
}
DollyShot.prototype.placeImages = function() {
	var _ds = this;
	var leftX = 0;
	_ds.targetHeight = _ds.target.height();
	for (var i = 0; i < _ds.cards.length; i++) {
		var card = _ds.cards[i];
		card.cardDom[0]._card = card;
		card.leftX = leftX;
		card.width = card.imageWidth + card.marginleft + card.marginRight;
		leftX += card.width;
		
		card.curtainDom.css({
			'opacity': 0,
			'position': 'absolute',
			'top': _ds.targetHeight,
			'left': card.marginleft + 'px',
			'width': card.imageWidth + 'px',
			'heigth': _ds.targetHeight / 2
		});
		card.curtainDom.show();
		card.cardDom.hover(function(event){
			_ds.showCurtain(_ds, event.currentTarget._card);
		}, function(event) {
			_ds.hideCurtain(_ds, event.currentTarget._card);
		});
	}
	_ds.xMax = leftX;
	_ds.speed = _ds.params.speed;
	_ds.running = false;
	_ds.stepTime = _ds.params.stepTime;
	this.update();
	
	_ds.target.hover(function(event) {
		_ds.stop();
	}, function(event) {
		_ds.start();
	});
}
DollyShot.prototype.update = function() {
	var _ds = this;
	var maxX = _ds.content.width();
	for (var i = 0; i < _ds.cards.length; i++) {
		var card = _ds.cards[i];
		var cardLeft = MyLib.mod((card.leftX - _ds.leftX), _ds.xMax);
		var cardRight = MyLib.mod((card.leftX + card.width - _ds.leftX), _ds.xMax);
		if (card.visible) {  
			if (cardRight >= 0 && cardRight < maxX || cardLeft >= 0 && cardLeft < maxX) {
				if (cardLeft > maxX) {
					cardLeft -= _ds.xMax;
				}
				$(card.cardDom).css({
					'position': 'absolute', 'left': cardLeft, 'top': '0px'
				});
				card.curCardLeft = cardLeft;
			} else {
				card.curCardLeft = null;
				card.cardDom.detach();
				card.visible = false;
			}
		} else {
			if (cardRight >= 0 && cardRight < maxX || cardLeft >= 0 && cardLeft < maxX) {
				if (cardLeft > maxX) {
					cardLeft -= _ds.xMax;
				}
				$(card.cardDom).css({
					'position': 'absolute', 'left': cardLeft, 'top': '0px'
				});
				card.curCardLeft = cardLeft;
				_ds.content.append(card.cardDom);
				card.visible = true;
			}
		}
	}
}
DollyShot.prototype.step = function() {
	var _ds = this;
	var curTime = (new Date()).getTime();
	_ds.leftX += _ds.speed * (curTime - _ds.lastTime) / 1000;
	_ds.leftX = MyLib.mod(_ds.leftX, _ds.xMax);
	_ds.lastTime = curTime;
	this.update();
}
DollyShot.prototype.start = function() {
	var _ds = this;
	if (_ds.imagesToLoad > 0) {
		_ds.toBeStarted = true;
		return;
	}
	if (!_ds.running) {
		var doStep = function() {
			if (_ds.running) {
				_ds.step();
				_ds.timer = setTimeout(doStep, _ds.stepTime);
			}
		}
		_ds.running = true;
		_ds.lastTime = (new Date()).getTime();
		_ds.timer = setTimeout(doStep, _ds.stepTime);
	}
}
DollyShot.prototype.showCurtain = function(_ds, card) {
	card.curtainDom.stop(true, false).animate({
		'opacity': card.tissueOpacity,
		'top': card.tissueTop
	}, _ds.params.tissueAnimDuration);
}
DollyShot.prototype.hideCurtain = function(_ds, card) {
	card.curtainDom.stop(true, false).animate({
		'opacity': 0,
		'top': _ds.targetHeight
	}, _ds.params.tissueAnimDuration);
}
DollyShot.prototype.stop = function() {
	var _ds = this;
	if (_ds.running) {
		_ds.running = false;
		clearTimeout(_ds.timer);
	}
}
