/* <copyright>
This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
(c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
</copyright> */

////////////////////////////////////////////////////////////////////////
//
var Montage = 	require("montage/core/core").Montage,
	Component = require("montage/ui/component").Component;
////////////////////////////////////////////////////////////////////////
//Exporting as ColorWheel
exports.GradientPicker = Montage.create(Component, {
	////////////////////////////////////////////////////////////////////
	//
	hasTemplate: {
        value: true
    },
    ////////////////////////////////////////////////////////////////////
    //
    _updating: {
        value: false
    },
    ////////////////////////////////////////////////////////////////////
    //
    _value: {
        value: null
    },
	////////////////////////////////////////////////////////////////////
    //
    value: {
        get: function() {return this._value;},
        set: function(value) {this._value = value;}
    },
    ////////////////////////////////////////////////////////////////////
    //
    _mode: {
        value: 'linear'
    },
	////////////////////////////////////////////////////////////////////
    //
    mode: {
        get: function() {return this._mode;},
        set: function(value) {
        	//
        	this.application.ninja.colorController.colorPopupManager.hideGradientChipPopup();
        	//
            this._mode = value;
            //
            this._dispatchEvent('change', false);
        }
    },
    ////////////////////////////////////////////////////////////////////
    //
    _trackData: {
	    value: {width: 0, x: 0, y: 0}
    },
    ////////////////////////////////////////////////////////////////////
    //
    prepareForDraw: {
    	value: function() {
    		//
		}
    },
    ////////////////////////////////////////////////////////////////////
    //
    willDraw: {
    	value: function() {
    		//Getting component views from layout
    		this._trackData.width = parseInt(getComputedStyle(this.trackChips).getPropertyCSSValue('width').cssText);
    		//TODO: Fix events and remove this hack
    		this.trackCover.addEventListener('mouseover', function () {
				if (!this._updating) {    		
	    			this.trackCover.style.display = 'none';
    			}
    		}.bind(this), true);
    		//
    		this.radioLinear.addEventListener('change', function (e){
    			this.mode = 'linear';
    		}.bind(this), true);
    		//
    		this.radioRadial.addEventListener('change', function (e){
    			this.mode = 'radial';
    		}.bind(this), true);	
		}
    },
    ////////////////////////////////////////////////////////////////////
    //
    draw: {
    	value: function() {
    		//Checking for mode to assign radio value
    		if (this.mode === 'linear') {
    			this.radioLinear.checked = 'true';
    		} else if (this.mode === 'radial') {
    			this.radioRadial.checked = 'true';
    		}
    		//Checkign for value to initialize stops
    		if (!this.value) {
    			this.addDefaultStops();
			} else {
				//Adding stops from preset value
				for (var i=0, stops = this.value; stops[i]; i++) {
					this.addStop({color: {mode: stops[i].mode, value: stops[i].value}, percent:stops[i].position}, true);
				}
			}
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
   	didDraw: {
    	value: function() {
			//Adding event listener for stops
			this.trackMain.addEventListener('click', this, false);
    		//Getting position of track
    		var point = webkitConvertPointFromNodeToPage(this.trackMain, new WebKitPoint(0, 0));
    		//Setting position of track to calculate movement
    		this._trackData.x = point.x;
    		this._trackData.y = point.y;	
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //Default stops funtion (reset)
    addDefaultStops: {
    	value: function() {
    		this.addStop({color: {mode: 'rgb', value: {r: 255, g: 255, b: 255, a: 1, css: 'rgb(255, 255, 255)'}}, percent: 0}, true);
			this.addStop({color: {mode: 'rgb', value: {r: 0, g: 0, b: 0, a: 1, css: 'rgb(0, 0, 0)'}}, percent: 100}, true);
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
   	addStop: {
    	value: function(data, silent) {
    		if (this.application.ninja.colorController.colorPopupManager) {
    			//Hiding any open popups (of gradient buttons)
    			this.application.ninja.colorController.colorPopupManager.hideGradientChipPopup();
    			//Creating stop elements
    			var stop = document.createElement('div'),
    				holder = document.createElement('div'),
					tooltip = document.createElement('span'),
					button = document.createElement('button');
				//Setting up elements
				stop.appendChild(tooltip);
				stop.appendChild(holder);
				holder.appendChild(button);
				//Adding events to the stops
				stop.addEventListener('mousedown', this, false);
				stop.addEventListener('mouseup', this, false);
				//Storing refereces to buttons and actual stop container
				button.stop = stop;
				tooltip.stop = stop;
				stop.button = button;
				//Adding stop to container
				this.trackChips.appendChild(stop);
				//Checking for bounds to add stop
				if (data.percent >= 0 && data.percent <= 100) {
					this.positionStop(stop, data.percent);
					button.stopPosition = data.percent;
				}
				//Creating an instance of input chip
				this.application.ninja.colorController.addButton('chip', button);
				//Initialing button with color data
				button.color(data.color.mode, data.color.value);
				//Button popup data
				button.props = {side: 'top', align: 'center', nocolor: false, wheel: true, palette: false, gradient: false, image: false, offset: -84, gradientPopup: true, history: false};
				//Listening for color events from button
				button.addEventListener('change', this, false);
				//Dispatching event depending on type of mode
				if (!silent) {
					this._dispatchEvent('change', false);
				} else {
					this._dispatchEvent('change', true);
				}
				//
    		} else {
    				//Handle Error
    		}
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    removeStop: {
    	value: function(stop) {
    		var i, buttons = this.trackChips.getElementsByTagName('button');
    		//
    		if (buttons.length > 2) {
    			//Removing stops
    			this.trackChips.removeChild(stop);
    			//Stopping events related to this current stop
    			this.removeStopMoving();
    		}
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    removeStopMoving: {
    	value: function() {
    		this._updating = false;
    		this.trackCover.style.display = 'none';
			this._dispatchEvent('change', false);
			document.removeEventListener('mousemove', this, false);
			document.removeEventListener('mouseup', this, false);
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    positionStop: {
    	value: function(stop, percent) {
    		try {
    			if (percent<0) {
	    			percent = 0;
	    		} else if (percent>100) {
	    			percent = 100;
	    		}
	    		//
    			var adj = (parseInt(getComputedStyle(stop).getPropertyCSSValue('width').cssText)*percent/100)/this._trackData.width;
    			stop.style.left = Math.round(percent-Math.round(adj*100))+'%';
    			stop.button.stopPosition = percent;
    		} catch (e) {
    			//TEMP
    		}
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //TODO: Add color detection canvas to get actual color
    handleClick: {
    	value: function(e) {
    		//Logic to get color from canvas data would go here
    		var data = {};
    		data.mode = 'rgb';
    		data.value = {r: 100, g: 100, b: 100, a: 1, css: 'rgb(100, 100, 100)'};
    		//
    		this.addStop({color: data, percent: Math.round(100*(e._event.offsetX/e._event.target.offsetWidth))});
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    handleMouseup: {
    	value: function(e) {
			this.removeStopMoving();
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    handleMousedown: {
    	value: function(e) {
			//
			var i, buttons = this.trackChips.getElementsByTagName('button');
			this.currentStop = e._event.target.stop;
    		//Looping through other stops to swap depths
    		for (i=0; buttons[i]; i++) {
    			buttons[i].stop.style.zIndex = 1;
    		}
			//Setting the depth of the current button to the highest
			this.currentStop.style.zIndex = buttons.length+1;
			//Adding events for actions while moving
			document.addEventListener('mousemove', this, false);
			document.addEventListener('mouseup', this, false);
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    handleMousemove: {
    	value: function(e) {
    		//
    		this._updating = true;
    		//
    		this.application.ninja.colorController.colorPopupManager.hideGradientChipPopup();
    		//
    		if (e._event.y > this._trackData.y+70 || e._event.y < this._trackData.y) {
    			this.removeStop(this.currentStop);
    		}
    		//
    		if (this.currentStop.button.stopPosition !== Math.round((e._event.x-this._trackData.x)/this._trackData.width*100)) {
    			this.trackCover.style.display = 'block';
    		}
    		//
    		this.positionStop(this.currentStop, Math.round((e._event.x-this._trackData.x)/this._trackData.width*100));
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //
    handleChange: {
    	value: function(e) {
    		this.application.ninja.colorController.colorView.colorManager.input = this.application.ninja.colorController.colorView.previousInput;
			this._dispatchEvent('change', false);
			this.application.ninja.colorController.colorView.colorManager.input = 'chip';
    	}
    },
    ////////////////////////////////////////////////////////////////////
    //Dispatching custom event
    _dispatchEvent: {
        value: function(type, userInitiated) {
        	//
        	var actionEvent = document.createEvent("CustomEvent"), buttons = this.trackChips.getElementsByTagName('button'), stops = [], css, previewCss = '-webkit-gradient(linear, left top, right top';
        	//Preventing an events of less than 2 stops since there'll be a reset
        	if (buttons.length < 2) {
        		return;
        	}
        	//Initializing CSS string
        	if (this.mode === 'radial') {
        		css = '-webkit-radial-gradient(center, ellipse cover';
        	} else {
        		css = '-webkit-gradient(linear, left top, right top';
        	}
        	//Creating stops array
        	for (var i=0; i < buttons.length; i++) {
        		stops.push({value: buttons[i].colorValue, mode: buttons[i].colorMode, position: buttons[i].stopPosition});
        	}
        	//Sorting array (must be sorted for radial gradients, at least in Chrome
        	stops.sort(function(a,b){return a.position - b.position});
        	//Looping through stops in gradient to create CSS (actual and preview)
        	for (var i=0; i < stops.length; i++) {
        		//Addint to CSS String
        		if (this.mode === 'radial' && stops[i].value) {
        			css += ', '+stops[i].value.css+' '+stops[i].position+'% ';
        			//The CSS string for the preview bar is always linear
	        		previewCss += ', color-stop('+stops[i].position+'%,'+stops[i].value.css+')';
        		} else if (stops[i].value){
	        		css += ', color-stop('+stops[i].position+'%,'+stops[i].value.css+')';
	        		//The CSS string for the preview bar is always linear
	        		previewCss += ', color-stop('+stops[i].position+'%,'+stops[i].value.css+')';
        		} else {
        			//
        		}
        	}
        	//Closing the CSS strings
        	css += ')';
        	previewCss += ')';
        	//console.log(previewCss);
        	//Setting the preview track background
        	this.trackMain.style.background = previewCss;
        	//Storing the stops
        	this.value = stops;
        	//Initializing and storing data for event
            actionEvent.initEvent(type, true, true);
            actionEvent.type = type;
            actionEvent.wasSetByCode = userInitiated;
            actionEvent.gradient = {stops: this.value, mode: this.mode, gradientMode: this.mode, css: css};
            this.dispatchEvent(actionEvent);
        }
    }
    ////////////////////////////////////////////////////////////////////
});