define([
		'lodash/lodash'
	],
	function(_) {
		var tooltip = function($document, $animate, $q, $compile, $interpolate, $timeout, $templateCache, $rootScope) {
			var self = this;

			//	TOOLTIP PRIV VARIABLES
			var __current = null;
			var __previous = null;
			var __scope = null;

			//	STATE PRIV VARIABLES
			var __orientation = 'top';
			var __distance = 25;
			var __context = {};
			var __content = '<div>Hi im a tooltip!</div>';
			var __position = [0, 0];
			var __containerTemplate = 'tameka.tooltip.template.html';
			var __class;
			var __animated = true;

			// we need to offset because the TL of the tooltip will initially be at the cursor
			var offsetPosition = function() {
				var rv = angular.copy(__position);

		        var width = __current.prop('offsetWidth');
		        var height = __current.prop('offsetHeight');

				switch(__orientation) {
					case 'top':
						rv[0] += -width / 2;
						rv[1] += -(height + __distance);
						break;
					case 'left':
						rv[0] += -(width + __distance);
						rv[1] += -height / 2;
						break;
					case 'right':
						rv[0] += __distance;
						rv[1] += -height / 2;
						break;
					case 'bottom':
						rv[1] += __distance;
						break;
				}

				return rv;
			}

			var cleanTooltip = function() {
				if(!_.isNull(__previous)) {
					__previous.remove()
					__previous = null;
				}

				if(!_.isNull(__scope)) {
					__scope.$destroy();
					__scope = null;
				}

				if(!_.isNull(__current)) {
					$animate.leave(__current).then(function() {
						__previous = null;
					});

					__previous = __current;
					__current = null;

					// is this tooltip being envoked in an angular environment?
					var phase = $rootScope.$$phase;
					if(phase != '$apply' && phase != '$digest') {
						$rootScope.$apply()
					}
				}
			}

			// render and place tooltip in DOM
			var createTooltip = function() {
				// create a new scope for our tt
				__scope = $rootScope.$new(true);
				angular.extend(__scope, __context);

				__scope.content = $interpolate(__content)(__scope);
				__scope.placement = __orientation;
				__scope.classes = __class;

				if(__animated) {
					__scope.classes += ' animate';
				}

				var linker = $compile($templateCache.get(__containerTemplate));

				__current = linker(__scope, function(tooltip, scope) {
					tooltip.css({visibility: 'hidden'})
					$animate.enter(tooltip, $document.find('body'))
				});
			}

			return {
				setOrientation: function(orientation) {
					__orientation = orientation;

					return this;
				},
				setDistance: function(distance) {
					__distance = distance;

					return this;
				},
				setContext: function(context) {
					__context = context

					return this;
				},
				setContent: function(content) {
					__content = content;

					return this;
				},
				setPosition: function(position) {
					__position = position;

					return this;
				},
				setContainerTemplate: function(template) {
					__containerTemplate = template;

					return this;
				},
				addClass: function(userClass) {
					__class = userClass;

					return this;
				},
				setAnimation: function(animated) {
					__animated = animated;

					return this;
				},


				create: function() {
					var retObj = this;

					cleanTooltip();
					createTooltip();

					// wait until tooltip is in DOM to offset (otherwise the tooltip has
					//	no width etc)
					$timeout(function() {
						retObj.move()
					}, 0)
				},
				move: function() {
					if(!_.isNull(__current)) {
						var offsets = offsetPosition();
						__current.css({
							top: offsets[1].toString() + 'px',
							left: offsets[0].toString() + 'px',
							visibility: 'visible'
						});
					}
				},
				remove: function() {
					cleanTooltip();
				}
			}
		}

		return tooltip;
	}
)