var app = angular.module('dataTransformer', ['ngFileUpload'])

app.directive('flowElement', function() {
    return {
        link: function($scope, element, attrs) {
            // Trigger when number of children changes,
            // including by directives like ng-repeat
            var watch = $scope.$watch(function() {
                return element.children().length;
            }, function() {
                // Wait for templates to render
                $scope.$evalAsync(function() {
                    // Finally, directives are evaluated
                    // and templates are renderer here
                    var children = element.children();
                    //console.log(children);
                    
                    $scope.renderPlumb();
                });
            });
        },
    };
});

app.controller('ImportConfigurationController',['$scope', '$http', 'Upload', function($scope, $http, Upload) {
    $scope.title= "Map your source file to output file";
    $scope.sourceElements = [];
    $scope.destinationElements = [];
    $scope.mappings = [];
    $scope.sourceFileName = "";
    
    $scope.recurringElement = "";
    $scope.currentElement = 0;
    $scope.lastDestinationElementsLength = 0;
    
    $scope.upload = function (files) {
        if (files && files.length) {
            for (var i = 0; i < files.length; i++) {
                var file = files[i];
                Upload.upload({
                    url: 'source',
                    fields: {'username': "dummy_user"},
                    file: file
                }).progress(function (evt) {
                    var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
                    console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
                }).success(function (data, status, headers, config) {
                    //console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
                    $scope.sourceFileName = config.file.name;
                    
					var keys = [];
					keys = keys.concat($scope.getProperties(data));
					console.log($scope.sourceElements.length);
                });
            }
        }
    };
    
    $scope.getProperties = function toArray(obj) {
        var result = [];
        for (var prop in obj) {
        	
            var value = obj[prop];
            if (typeof value === 'object') {
                result.push(toArray(value)); // <- recursive call
            }
            else {
            	//console.log(prop);
            	if (prop === 'name'){
            		result.push(value);
            		$scope.sourceElements.push(value); //Super hack
            	}
            	
            	if (prop === 'maxOccurs' && value === 'unbounded'){
            		//console.log($scope.sourceElements[$scope.sourceElements.length - 1]);
            		$scope.recurringElement = $scope.sourceElements[$scope.sourceElements.length - 1];
            	}
            }
        }
        return result;
    }
    
    $scope.addDestinationElement = function addDestinationElement(value) {
    	$scope.destinationElements.push(value);	
    }
    
    $scope.getExampleCsvFile = function getExampleCsvFile(){
    	var data = JSON.stringify($scope.mappings);
    	var filename = $scope.sourceFileName;
    	var repeatingElement = $scope.recurringElement;
    	
        $http.post('/datamappings/example/csv?filename=' + filename + "&repeating-element=" + repeatingElement, data).success(function(data) {	  
	      	 //console.log(data);
	      	 
	      	 //TODO: <Put this in a directive>
	         
             var hiddenElement = document.createElement('a');
             hiddenElement.href = 'data:attachment/csv,' + encodeURI(data);
             hiddenElement.target = '_blank';
             hiddenElement.download = 'sample.csv';
             hiddenElement.click();
	      	 
	      	 //</Put this in a directive>
	      	 
	      	 return data;
        });
    }
    
    $scope.saveMappings = function saveMappings(){
    	console.log("save");
    	
    	var data = JSON.stringify($scope.mappings);
    	var filename = $scope.sourceFileName;
   	
    	$http.put('/datamappings/?filename=' + filename + "&repeating-element=book", data).success(function(data) {	  
        //$http.post('/mappings/?filename=' + filename, data).success(function(data) {	  
	      	 console.log(data);
        });
    }
    
    $scope.renderPlumb = function render() {
    	//console.log(document.getElementById('file-mapping-section').getBoundingClientRect());
    	
    	jsPlumb.ready(function() {
    		var instance = jsPlumb.getInstance({
    	        // default drag options
    	        DragOptions: { cursor: 'pointer', zIndex: 2000 },
    	        // the overlays to decorate each connection with.  note that the label overlay uses a function to generate the label text; in this
    	        // case it returns the 'labelText' member that we set on each connection in the 'init' method below.
    	        ConnectionOverlays: [
    	            [ "Arrow", { location: 1 } ],
    	            [ "Label", {
    	                location: 0.3,
    	                id: "label",
    	                cssClass: "aLabel"
    	            }]
    	        ],
    	        Container: "mapping-section"
    	    });

	        var basicType = {
	            connector: "StateMachine",
	            paintStyle: { strokeStyle: "red", lineWidth: 4 },
	            hoverPaintStyle: { strokeStyle: "blue" },
	            overlays: [
	                "Arrow"
	            ]
	        };

	        instance.registerConnectionType("basic", basicType);

	        // this is the paint style for the connecting lines..
	        var connectorPaintStyle = {
	                lineWidth: 4,
	                strokeStyle: "#61B7CF",
	                joinstyle: "round",
	                outlineColor: "white",
	                outlineWidth: 2
	            },
	        // .. and this is the hover style.
	            connectorHoverStyle = {
	                lineWidth: 4,
	                strokeStyle: "#216477",
	                outlineWidth: 2,
	                outlineColor: "white"
	            },
	            endpointHoverStyle = {
	                fillStyle: "#216477",
	                strokeStyle: "#216477"
	            },
	        // the definition of source endpoints (the small blue ones)
	            sourceEndpoint = {
	                endpoint: "Dot",
	                paintStyle: {
	                    strokeStyle: "#7AB02C",
	                    fillStyle: "transparent",
	                    radius: 7,
	                    lineWidth: 3
	                },
	                isSource: true,
	                connector: [ "Flowchart", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true } ],
	                connectorStyle: connectorPaintStyle,
	                hoverPaintStyle: endpointHoverStyle,
	                connectorHoverStyle: connectorHoverStyle,
	                dragOptions: {},
	                overlays: [
	                    [ "Label", {
	                        location: [0.5, 1.5],
	                        label: "",
	                        cssClass: "endpointSourceLabel"
	                    } ]
	                ]
	            },
	        // the definition of target endpoints (will appear when the user drags a connection)
	            targetEndpoint = {
	                endpoint: "Dot",
	                paintStyle: { fillStyle: "#7AB02C", radius: 11 },
	                hoverPaintStyle: endpointHoverStyle,
	                maxConnections: -1,
	                dropOptions: { hoverClass: "hover", activeClass: "active" },
	                isTarget: true,
	                overlays: [
	                    [ "Label", { location: [0.5, -0.5], label: "", cssClass: "endpointTargetLabel" } ]
	                ]
	            },
	            
	            init = function (connection) {	        	
	                connection.getOverlay("label").setLabel(connection.sourceId + "-" + connection.targetId);
	            };   
	               
	        //console.log($scope.currentElement);
	        
	        //TODO: this needs to be refactored. This if statement has been put in place for optimization reasons (1st clause). Second clause needed to be included otherwise target endpoints cannot be bound to.
	        if ($scope.currentElement == $scope.sourceElements.length - 1 || $scope.destinationElements.length > $scope.lastDestinationElementsLength) {
	            for (var i = 0; i < $scope.sourceElements.length; i++) {
	            	//instance.draggable($scope.sourceElements[i]);
	    	        //console.log('- ' + i);
	            	
	                instance.addEndpoint($scope.sourceElements[i], sourceEndpoint, {
	                    anchor: ["Right"], uuid: $scope.sourceElements[i]
	                });
	            }
	            
	            for (var i = 0; i < $scope.destinationElements.length; i++) {
	            	//instance.draggable($scope.destinationElements[i]);
	            	
	                instance.addEndpoint($scope.destinationElements[i], targetEndpoint, { 
	                	anchor: ["Left"], uuid: $scope.destinationElements[i] 
	                });
	            }
	            
	            $scope.lastDestinationElementsLength = $scope.destinationElements.length;
	        }
            
            $scope.currentElement = $scope.currentElement + 1;
            
        	instance.bind("connection", function(info) {
                init(info.connection);
        		
        		var mapping = {};
        		mapping["source"] = info.sourceId;
        		mapping["target"] = info.targetId;
        		
        		var lookup = {};
        		for (var i = 0, len = $scope.mappings.length; i < len; i++) {
        		    lookup[$scope.mappings[i].source] = $scope.mappings[i];
        		}
        		
        		if (!lookup[info.sourceId]) {
        			$scope.mappings.push(mapping);
        		}
        		
        		$scope.$digest();
    		});
        	
        	instance.bind("connectionDetached", function(info) {
          		var mapping = {};
        		mapping["source"] = info.sourceId;
        		mapping["target"] = info.targetId;
        		
        		for(var i = $scope.mappings.length - 1; i >= 0; i--) {
        		    if($scope.mappings[i].source === info.sourceId) {
        		    	$scope.mappings.splice(i, 1);
        		    }
        		}
    		});	
        	
            //
            // listen for clicks on connections, and offer to delete connections on click.
            //
            instance.bind("click", function (conn, originalEvent) {
               // if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?"))
                 //   instance.detach(conn);
                conn.toggleType("basic");
            });

            instance.bind("connectionDrag", function (connection) {
                console.log("connection " + connection.id + " is being dragged. suspendedElement is ", connection.suspendedElement, " of type ", connection.suspendedElementType);
            });

            instance.bind("connectionDragStop", function (connection) {
                console.log("connection " + connection.id + " was dragged");
            });

            instance.bind("connectionMoved", function (params) {
                console.log("connection " + params.connection.id + " was moved");
            });
        });
    }   
}]);