'use strict';

/**
 *@author
 *A module representing the custom draggable functions
 *@Module sgDraggable
 */
define(['jquery', 'jquery-drag', 'jquery-hittest'], function($, sound, buttonsManager) {

	
	var app = {};

	function calculatePosition(objElement, strOffset) {
		var iOffset = 0;
		if (objElement.offsetParent) {
			do {
				iOffset += objElement[strOffset];
				objElement = objElement.offsetParent;
			} while (objElement);
		}
		return iOffset;
	}

	app.resetDraggable = function(selector) {
		$(selector).each(function(i,e){
				var $this = $(this);
				var dragObjs = $this.data("dragObj");
				if(dragObjs != undefined) dragObjs.remove();
				var dropSelector = $this.attr("data-sg-drop-selector");
				$this.css("visibility", "visible");
				if(dropSelector){
					$(dropSelector).each(function(i,e){
						$(this).data("dragObj", null);
					});
				}
			});
	}

	app.setDraggable = function(selector, options) {

		/*
				var defaultOption = {
					revert: null,
					success: null,
					fail: null,
					dropSelector:null
				}
				*/
		//console.log(options);
		var options = options || {};
		//console.log(options);
		//var cloneVal;
		$(selector)
			.each(function(i, e) {
				var $this = $(this);
				var draggableOptions = {
					dropSelector: options.dropSelector || $this.attr("data-sg-drop-selector"),
					revert: (function() {
						var r = options.revert || $this.attr("data-sg-revert");
						return typeof r === "string" ? JSON.parse(r) : r;
					})(),
					fail: options.fail || $this.attr("data-sg-drop-fail"),
					success: options.success || $this.attr("data-sg-drop-success"),
					start: options.start || $this.attr("data-sg-drop-start"),
					clone: (function() {
						var r = options.clone || $this.attr("data-sg-clone");
						return typeof r === "string" ? JSON.parse(r) : r;
					})()
				};

				//cloneVal = draggableOptions.clone ? "clone" : undefined;
				//console.log(cloneVal);
				//console.log(draggableOptions);

				$this.attr("data-sg-drop-selector", draggableOptions.dropSelector);
				$this.attr("data-sg-revert", draggableOptions.revert);
				$this.attr("data-sg-drop-fail", typeof draggableOptions.fail === "string" ? draggableOptions.fail : "");
				$this.attr("data-sg-drop-success", typeof draggableOptions.success === "string" ? draggableOptions.success : "");
				$this.attr("data-sg-drop-start", typeof draggableOptions.start === "string" ? draggableOptions.start : "");
				$this.attr("data-sg-clone", draggableOptions.clone);

				$this.data("draggableOptions", draggableOptions);

				$this.data("originPos", {
					left: this.offsetLeft,
					top: this.offsetTop
				});


				// 			///////////////////////////draggable////////////////////////////////////
				$this.draggable({

					helper: (function() {
						return draggableOptions.clone ? "clone" : undefined;
					})(),
					cursor: 'pointer',
					revert: function() {
						
						

						var options = this.data("draggableOptions");
						var failAction = options.fail;
						var successAction = options.success;
						var startAction = options.start;
						var dropselector = options.dropSelector;
						var bool = options.revert;
						var isClone = options.clone;

						/*
 							bool = (options.revert == undefined) ? 
 								(this.attr("data-sg-revert") == "true" ? true : false)
 								:options.revert;
 							failAction = options.fail || this.attr("data-sg-drop-fail");
 							successAction = options.success || this.attr("data-sg-drop-success");
 							dropselector = options.dropSelector || this.attr("data-sg-drop-selector");

 							bool = options.revert == "true" ? true : false;
 							*/

						var hit = false;
						//console.log($(this).data("cloneTarget"));
						var rect = (this.data("cloneTarget") || this).getRect();
						if (dropselector) {
							//드랍체크.  드래그 대상의 가운데 좌표가 드랍대상안에 들어오는지 확인
							$(dropselector).each(function(i, e) {
								if (hit) return;

								hit = $(this).hitTestPoint({
									x: rect.x + rect.width * 0.5 * sg.scaleX,
									y: rect.y + rect.height * 0.5 * sg.scaleY,
									transparency: false,
									scaleX: sg.scaleX,
									scaleY: sg.scaleY
								});
								/*
 									hit = $(this).hitTestObject({
 										selector: this,
 										transparency: false,
 										scaleX: sg.scaleX,
 										scaleY: sg.scaleY
 									});
 									*/
							});

						}

						/*
 							스케일이 줄어든 상태에서 jQuery의 offset이 제대로 동작하지 않는다.
 							드래그객체의 복사본을 만들고, 절대 좌표값으로 드랍대상의 가운데에 위치하도록 하자.

 							절대좌표값을 갖는 복사본을 만드는 이유는, relative상태로 드랍대상의 위치를 계산하기 힘들기 때문.
 							현재 드래그객체를 absolute로 바꾸면 빈자리를 체우기위해 이하 DOM요소들이 올라온다.
 							*/


						if (hit) {
							//bool = false;
							var soff = $stage.offset();
							var $clone = this.clone()
								.css("position", "absolute")
								.appendTo($stage).css({
									left: calculatePosition(hit[0], "offsetLeft") + (hit.width() - this.width()) * 0.5 - soff.left,
									top: calculatePosition(hit[0], "offsetTop") + (hit.height() - this.height()) * 0.5 - soff.top
								});
							
							$clone.data("hit", hit);
							hit.data("dragObj", $clone);
							//Add to allow resetDraggable
							this.data("dragObj",$clone);


							if (!isClone) {
								this.css("visibility", "hidden"); //.draggable("disable");
							}

							if (successAction) {
								if (typeof successAction == "function") {

									
									successAction.apply($clone[0]);
								} else {
									eval(successAction);
								}
							}
						} else if (!hit && failAction) {
							if (typeof failAction == "function") {
								failAction.apply(this[0]);
							} else {
								eval(failAction);
							}
						}

						if (bool && this.css("position") == "absolute") {
							bool = false;
							this.animate(this.data("originPos"));
							// console.log(this);
							// console.log(this.data("originPos"));
						}
						return bool;
					},
					start: function(e, ui) {
						var options = $(this).data("draggableOptions");
						var startAction = options.start;

						//console.log(ui.helper);
						if ($(this).css("position") != "absolute") {
							ui.position.left *= sg.scaleX;
							ui.position.top *= sg.scaleY;
						}

						$(this)
							.data("disPos", {
								left: ui.position.left - e.clientX,
								top: ui.position.top - e.clientY
							}).css("z-index", sg.zidx++);

						if (startAction) {
							if (typeof startAction == "function") {
								startAction.apply($(this)[0]);
							} else {
								eval(startAction);
							}
						}

						var op = $(this).data("draggableOptions");
						if (op && op.clone) {
							$(this).data("cloneTarget", ui.helper);
						}
					},
					drag: function(e, ui) {
						var disPos = $(this).data("disPos");
						ui.position = {
							left: (disPos.left + e.clientX) / sg.scaleX,
							top: (disPos.top + e.clientY) / sg.scaleY
						};
					}
				});

			})

	}


	return app;

})