/**
 * @jsx React.DOM
 */
window.aperture = React.createClass({displayName: "aperture",

	statics: {
		count: 0
	},

	getInitialState: function(){

		return {
			prefix: "svg-aperture-react_" + (window.aperture.count++)
		};

	},

	getMaskStyle: function(){

		return {
			'clipPath': 'url(#'+this.state.prefix+'_mask)'
		};

	},

	broadcastToAngular: function(){
		if(this.props.svgModel.type == 'image-text')
			this.props.scope.$emit('svgAperture.click', [this.props.svgModel, {}]);

	},

	render: function() {
		return React.createElement("svg", {style:  {'overflow': 'visible'}, onClick: this.broadcastToAngular, onTouchStart: this.broadcastToAngular}, 
					React.createElement("defs", null, 
						React.createElement("clipPath", {id: this.state.prefix+'_mask'}, 
							React.createElement("rect", {width: this.props.svgModel.width, height: this.props.svgModel.height, x: "0", y: "0"})
						)
					), 
					React.createElement("g", {width: this.props.svgModel.width, height: this.props.svgModel.height, transform: 'translate('+this.props.svgModel.x+', '+this.props.svgModel.y+')', style:  this.getMaskStyle() }, 
						React.createElement("g", null, this.props.children)
					)
				);
	}
});

window.imageAperture = React.createClass({displayName: "imageAperture",


	getInitialState: function(){

		var self = this;

		self._data = {};

		self._data.actualImageWidth = 0;
		self._data.actualImageHeight = 0;

		return {
			imageLoaded: false
		};

	},

	getDefaultProps: function(){
	
		return {
			svgModel: {
                point: {x:0.5,y:0.5},
                rotate: 90,
                zoom: 0
            }
		};

	},

	componentWillReceiveProps: function(nextProps) {
	    this.loadImage();  
	},

	componentWillMount: function(){
		this.loadImage();
	},

	loadImage: function(){

		var self = this;

		if(!self.props.src)
			return;

		$('<img>')
			.attr('src', self.props.src)
			.load(function(){

			    var that = this;

                if(self.props.svgModel) {
                    self.props.svgModel.imgWidth = that.width;
                    self.props.svgModel.imgHeight = that.height;
                }

                self._data.actualImageWidth = that.width;
                self._data.actualImageHeight = that.height;
                self.state.imageLoaded = true;

                self.forceUpdate();

			});
	
	},


	calculateImageTagData: function(){

		var self = this;

	    if(!self.state.imageLoaded || typeof self.props.apertureData != 'object') {

	        self._data.imageTag = {
	            x: 0,
	            y: 0,
	            width: 0,
	            height: 0,
	            rotate: 0,
	            rotationPoint: {x:0, y:0}
	        };

	        return;

	    }

	    self._data.imageTag = angular.copy(self._data.image);

	    var iT = self._data.imageTag;

	    if(iT.rotate%360 == 90 || iT.rotate%360 == 270 || iT.rotate%360 == -90 || iT.rotate%360 == -270) {
	        //swap(iT.width, iT.height);
	        var tmp = iT.width;
	        iT.width = iT.height;
	        iT.height = tmp;
	    }

	    iT.x = 0;
	    iT.y = 0;
	    iT.rotationPoint = {x:0,y:0};

	    if(iT.rotate%360 == 90 || iT.rotate%360 == -270) {
	        iT.y -= iT.height;
	    }

	    if(iT.rotate%360 == 180 || iT.rotate%360 == -180) {
	        iT.y -= iT.height;
	        iT.x -= iT.width;
	    }

	    if(iT.rotate%360 == 270 || iT.rotate%360 == -90) {
	        iT.x -= iT.width;
	    }

	    
	},

	calculateImageData: function(){

		var self = this;

	    if(!self.state.imageLoaded || typeof self.props.apertureData != 'object') {
	        
	        self._data.image = {
	            x: 0,
	            y: 0,
	            width: 0,
	            height: 0,
	            rotate: 0,
	            rotationPoint: {x:0, y:0}
	        };

	        return;
	    }

	    if(self.props.svgModel && self.props.svgModel.rotate)
	        var rotate = self.props.svgModel.rotate;

	    if(rotate%360 == 90 || rotate%360 == 270 || rotate%360 == -90 || rotate%360 == -270)
	        var imgR = self._data.actualImageHeight / self._data.actualImageWidth;
	    else
	        var imgR = self._data.actualImageWidth / self._data.actualImageHeight;

	    var frameR = self.props.apertureData.width / self.props.apertureData.height;

	        if(imgR > frameR) {
	            var height = self.props.apertureData.height;
	            var width = height * imgR;
	        } else {
	            var width = self.props.apertureData.width;
	            var height = width / imgR;
	        }

	    if(self.props.svgModel && self.props.svgModel.zoom < 1)
	        self.props.svgModel.zoom = 1;

	    width = self.props.svgModel.zoom * width;
	    height = self.props.svgModel.zoom * height;

	    var p = self.props.svgModel.point;

	    var x = (self.props.apertureData.width/2 - (p.x * width));
	    var y = (self.props.apertureData.height/2 - (p.y * height)); 

	    var rotationPoint = {
	        x: (self.props.apertureData.width)/2,
	        y: (self.props.apertureData.height)/2
	    };


	    self._data.image = {
	        x: x,
	        y: y,
	        width: width,
	        height: height,
	        rotate: rotate,
	        rotationPoint: rotationPoint
	    };

	},

	render: function() {

		this.calculateImageData();
		this.calculateImageTagData();

		var self = this;

		return React.createElement("svg", {"data-id": this.props.apertureData.asset_table_id, "data-table": this.props.apertureData.asset_table, "data-type": "svg-aperture-image"}, 
					React.createElement("g", null, 
						this.state.imageLoaded ? 

							React.createElement("svg", {
	 							viewBox: '0 0 '+self._data.image.width+' '+self._data.image.height, 
	 							x: self._data.image.x, 
	 							y: self._data.image.y, 
	 							height: self._data.image.height, 
	 							width: self._data.image.width, 
								dangerouslySetInnerHTML: {__html: '<image x="'+self._data.imageTag.x+'" y="'+self._data.imageTag.y+'" width="'+self._data.imageTag.width+'" height="'+self._data.imageTag.height+'" xlink:href="'+this.props.src+'" preserveAspectRatio="none" transform="rotate('+self._data.imageTag.rotate+' '+self._data.imageTag.rotationPoint.x+' '+self._data.imageTag.rotationPoint.y+')"></image>'}
							}
							)

						: null, 

						 self.props.apertureData.hover ? React.createElement("rect", {scale: self.props.scale, opacity: "0.7", fill: "#00ff12", stroke: "#00ff12", strokeWidth: "0", width: self.props.apertureData.width, height: self.props.apertureData.height}) : null
					)
				)
	}

});

window.textAperture = React.createClass({displayName: "textAperture",

	getFontFamily: function() {
		if(this.props.svgModel)
            return this.props.svgModel.fontFamily;
        else
            return '';
	},
	getStyle: function() {
		
		// var style = "font-family: '" + this.getFontFamily() + "';";
		var style = {"fontFamily": "'"+this.getFontFamily()+"'"};

		if(this.props.svgModel && this.props.svgModel.fontVariant) {
		    var fontVariant = this.props.svgModel.fontVariant;
		    if(fontVariant.indexOf('italic') != -1)
		    	style.fontStyle = "italic";
		        // style += 'font-style: italic;';

		    fontVariant = fontVariant.replace('italic', '');
		    if(fontVariant != 'regular') {
		    	style.fontWeight = "'"+fontVariant+"'";
		        // style += 'font-weight: '+fontVariant+';';
		    }

		}

		return style;
	},
	getVertAlign: function() {
		if(this.props.type == "large_dates")
			return true;

		return false;
	},
	getVertAlignHeight: function() {
		if(this.props.type == "large_dates")
			return this.props.apertureData.height;

		return false;
	},
	getWeekendWeight: function() {
		if(!this.props.svgModel.weekendWeight)
			return 'normal';

		return this.props.svgModel.weekendWeight;
	},
	getFontSize: function() {
		if(!this.props.dpi || isNaN(this.props.dpi))
		    this.props.dpi = 72;

		return (this.props.svgModel.fontSize) * (parseFloat(this.props.dpi)/72);
	},
	getPosition: function() {
		var y = this.props.svgModel.fontSize;
		var x = 0;
		if(!this.props.alignmentPadding)
		    this.props.alignmentPadding = 0;
		if(!this.props.type)
		    this.props.type = false;
		if(this.props.type == 'large_dates')
			this.props.svgModel.alignment = 'center';
		switch(this.props.svgModel.alignment) {
		    case 'left':
		        x = 0 + parseInt(this.props.alignmentPadding);
		    break;
		    case 'center':
		        x = this.props.apertureData.width/2;
		    break;
		    case 'right':
		        x = this.props.apertureData.width - parseInt(this.props.alignmentPadding);
		    break;
		}

		return {x:x, y:y};
	},
	textAnchor: function() {
		switch(this.props.svgModel.alignment) {
		    case 'left':
		        return 'start';
		    break;
		    case 'center':
		        return 'middle';
		    break;
		    case 'right':
		        return 'end';
		    break;
		}
	},
	render: function() {
		return React.createElement("svg", null, 
				React.createElement("g", {className: "text-locked"}, 
					React.createElement(window.textWrap, {textWrapWidth: this.props.apertureData.width, textWrapX: this.getPosition().x, textWrapY: this.getPosition().y, textWrapVerticalAlign: this.getVertAlign(), textWrapHeight: this.getVertAlignHeight(), textWrapLineHeight: this.getFontSize(), textWrapCaption: this.props.svgModel.caption, textWrapWeekendWeight: this.getWeekendWeight()}, 
						React.createElement("text", {style: this.getStyle(), fill: this.props.svgModel.color, fontSize: this.getFontSize(), textAnchor: this.textAnchor()})
					)
				)
			);
	}

});

window.textWrap = React.createClass({displayName: "textWrap",

	compile: function() {

	 	var domElem = this.getDOMNode();

	 	var elem = $(domElem);

	 	elem.attr('x',this.props.textWrapX);
	 	elem.attr('y',this.props.textWrapY);

	 	elem.empty();

	 	var textWrapCaption = this.props.textWrapCaption + '';

	 	if(!textWrapCaption)
	 		return;

	 	textWrapCaption = textWrapCaption.replace(new RegExp("\n", 'g'), " \n");

	 	var captionsArray = textWrapCaption.split(" ");

	 	var lines = [];

	 	var tempText = "";
	 	for (var i=0; i<captionsArray.length; i++) {

	 	  elem.empty();
	 	  elem.append(tempText + " " + captionsArray[i]);

	 	  if(domElem.getBBox().width > (this.props.textWrapWidth*0.9) || captionsArray[i].indexOf("\n") == 0) {

	 	    if(tempText.indexOf(" ") == 0)
	 	        tempText = tempText.substr(1);

	 	    lines.push(tempText);

	 	    tempText = captionsArray[i];
	 	  } else {
	 	    tempText += " " + captionsArray[i];
	 	  }
	 	}


	 	if(tempText.indexOf(" ") == 0)
	 	    tempText = tempText.substr(1);

	 	lines.push(tempText);
	 	elem.empty();


	 	var y = 0;
	 	for(i in lines) {

	 	    if(lines[i] == '' || lines[i] == ' ')
	 	        continue;

	 	    y = y + parseFloat(this.props.textWrapLineHeight);

	 	    var el = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
	 	    el.setAttribute('x', this.props.textWrapX);
	 	    el.setAttribute('y', y);

	 	    el.style.fontWeight = this.props.textWrapWeekendWeight;
			//el.style.filter  = 'alpha(opacity='+this.props.textWrapWeekendWeight+')';

	 	    var textNode = document.createTextNode(lines[i].trim());
	 	    el.appendChild(textNode);

	 	    elem.append(el);
	 	}

	 	this.props.textWrapDimension = domElem.getBBox();

	 	if(this.props.textWrapVerticalAlign && this.props.textWrapHeight) {
	 	    var height = this.props.textWrapDimension.height;
	 	    var dy = (parseFloat(this.props.textWrapHeight) - height)/2;

	 	    //dy = dy - parseFloat(this.props.textWrapLineHeight) + parseFloat(this.props.textWrapFontSize);

	 	    elem.find('tspan').each(function(){
	 	        $(this).attr('y', parseFloat($(this).attr('y')) + dy);
	 	    });	
	 	}
	},

	componentDidUpdate: function(){
		var that = this;
		setTimeout(function(){
			if(that.isMounted())
				that.compile();
		}, 100);
	},

	componentDidMount: function(){
		var that = this;
		setTimeout(function(){
			if(that.isMounted())
				that.compile();	
		}, 100);
	},

	render: function() {
		return this.props.children;
	}

});

window.googleWebFontsImporter = React.createClass({displayName: "googleWebFontsImporter",
	compile: function() {
	
		var domElem = this.getDOMNode();
		var importedFonts = [];

	 	var elem = $(domElem);

		if(!this.props.layers)
		    return;

		var html = '';
	
		for(var i in this.props.layers) {
			if(!this.props.layers[i])
				continue;
		    if((this.props.layers[i].type == 'text' || this.props.layers[i].type == 'image-text') && this.props.layers[i].text) {

		    	if(_.indexOf(importedFonts, this.props.layers[i].text.fontFamily)!=-1)
		    		continue;
				
		        html += '@import url(https://fonts.googleapis.com/css?family='+this.props.layers[i].text.fontFamily.replace(/ /g, '+')+':'+this.props.layers[i].text.fontVariant+');';
		        importedFonts.push(this.props.layers[i].text.fontFamily);
		    }
		}

		elem.empty();
		elem.append(html);
	},
	componentDidUpdate: function() {
		var that = this;
		setTimeout(function(){
			if(that.isMounted())
				that.compile();
		}, 100);
	},
	componentDidMount: function() {
		var that = this;
		setTimeout(function(){
			if(that.isMounted())
				that.compile();
		}, 100);
	},
	render: function() {
		return this.props.children;
	}
});

window.calendarRenderer = React.createClass({displayName: "calendarRenderer",

	render: function() {
		
		var that = this;

		return React.createElement("svg", {style:  {overflow: 'visible'} }, 

			React.createElement("rect", {x: this.props.apertureData.x, y: this.props.apertureData.y, width: this.props.apertureData.width, height: this.props.apertureData.height, style: {'opacity': this.props.apertureData.calBackgroundOpacity}, fill: this.props.apertureData.calBackgroundColor}), 

			 this.props.apertureData.sub_type == 'no_events' ? 
				React.createElement(window.googleWebFontsImporter, {layers: this.props.dateGridCoordinates}, 
				 	React.createElement("style", {type: "text/css"}
		          	)
		        )
			:null, 			

			_.map(this.props.dateGridCoordinates, function(row, i){

				return React.createElement("g", {className: "g-row", key: i}, 

						 that.props.apertureData.sub_type == 'default' || that.props.apertureData.sub_type == 'large_dates' ? React.createElement("g", null, 

							React.createElement(window.googleWebFontsImporter, {layers: row}, 
							 	React.createElement("style", {type: "text/css"}
					          	)
					        ), 

							_.map(row, function(cell, j){

								if(!cell || !cell.x)
									return null;

								return React.createElement("g", {className: "g-cell", key: j}, 

									 cell.dateType!='day' && that.props.apertureData.sub_type == 'default' ?
										React.createElement("g", null, 
											React.createElement("line", {
												style:  cell.dateType=='date' ? { 'strokeWidth':'2', 'stroke': that.props.apertureData.calLineColor } : { 'strokeWidth':'2', 'stroke': '#757575' }, 
												x1: cell.x + cell.width, 
												y1: cell.y, 
												x2: cell.x + cell.width, 
												y2: cell.y + cell.height}), 

											React.createElement("line", {
												style:  cell.dateType=='date' ? { 'strokeWidth':'2', 'stroke': that.props.apertureData.calLineColor } : { 'strokeWidth':'2', 'stroke': '#757575' }, 
												x1: cell.x, 
												y1: cell.y + cell.height, 
												x2: cell.x + cell.width, 
												y2: cell.y + cell.height})

										
										) : null, 

									 ((cell.dateType=='date' || cell.dateType=='day')) ? React.createElement("g", null, 
										 React.createElement(window.aperture, {svgModel: cell, scope: that.props.scope}, 
											that.props.apertureData.sub_type == 'default' ? React.createElement("rect", {width: cell.width, height: cell.height, fillOpacity: "0"}) : null,  cell.dateType=='date' ? React.createElement(window.imageAperture, {src: cell.src, apertureData: cell, svgModel: cell.image, scale: that.props.scale}) : null, React.createElement(window.textAperture, {apertureData: cell, svgModel: cell.text, scale: that.props.scale, dpi: that.props.dpi, type: that.props.apertureData.sub_type, alignmentPadding: 10})
										)
									)
									 : null


								);
							})
						) : React.createElement("g", null, 

							 React.createElement(window.aperture, {svgModel: row, scope: that.props.scope}, 
								React.createElement(window.textAperture, {apertureData: row, svgModel: row.text, scale: that.props.scale, dpi: that.props.dpi})
							)
						)
				);
				
			})
		);
	}

});