 require([
        "modules/MapController",
        "modules/Palette",
        "modules/Portal",
        "modules/Utils"
    ], function(MapController, Palette, Portal, Utils) {
        //Session Variables-----------------------------------------------------------------------------
        var mapController = new MapController.MapController("viewDiv");
        var paletteCollection = new Object; 
        paletteCollection.palettes = new Array; //where 0 is the latest and the rest are for the undo stack
        paletteCollection.current = 0;

        //Functions  -----------------------------------------------------------------------------------

        //Build the map and generate a palette from a random image
        function initialise(){
            mapController.buildMap().done(function () {
                createRandomPalette().done(function(){
                });
            });
        } 

        //Creates a palette from a random image 
        function createRandomPalette(){
            var paletteWait = $.Deferred();
            var myPalette = new Palette.Palette();
            paletteCollection.palettes.unshift(myPalette);
            //Unsplash Colours and Patterns collection
            var url = "//source.unsplash.com/collection/175083/400x248";
            //var url = "//lh3.googleusercontent.com/SO4jvgiZlVezRvc9yIoVy-kYL6xmMzPdsKycymYzGr5nZBheBwJKUY24pgfI_lCG28a_-ec934E=w640-h400-e365";
            $.get(url, function(data, status){
                createPaletteFromImage(url)            
            });
            return paletteWait.promise();
        }

        //Creates a palette from an image and applies it to the map
        function createPaletteFromImage(image){
            var paletteWait = $.Deferred();
            var myPalette = new Palette.Palette();
            paletteCollection.palettes.unshift(myPalette);
            
            getLatestPalette().generateColours(image).done(function(){
                updateSwatches(getLatestPalette());
                mapController.applyPalette(getLatestPalette());
                paletteWait.resolve();
            });       
                  
            return paletteWait.promise();
        }

        //returns the most recent palette in the collection
        function getLatestPalette(){
            return paletteCollection.palettes[0];
        }

        //returns where we are for the undo redo stack
        function getPalettePosition(){
            return paletteCollection.current;
        }

        //creates a new palette and puts it at the front of the collection
        function createNewPalette(){
            var myPalette = new Palette.Palette();
            paletteCollection.unshift(myPalette);
            //tbc
        }

        //takes a copy of the most recent palette in the collection 
        //this is the best way to make adjustments to a palette, whilst maintaining the undo/redo stack
        function duplicateLatestPalette(){
            paletteCollection.palettes.unshift(new Palette.Palette());
            paletteCollection.palettes[0].colours = paletteCollection[1].colours;
            paletteCollection,palettes[0].image = paletteCollection[1].image;

        }

        //Updates the colour swatches based on the palette you give it
        function updateSwatches(palette){
            for(colour in palette.colours){
                var c = parseInt(colour)+1;
                $(".swatch:nth-child(" + c + ")").css("background", palette.colours[colour]);
            }
        }

        //sets up the swatch editing UI
        $("[id^='swatch']").spectrum({
            showInput: true,  
            showInitial: true,
            preferredFormat: "hex",
            chooseText: "Apply",
            change: function(color) {
                $(this).css("background",  color.toHexString());
                duplicateLatestPalette();
                var id = this.id.substring(7, 8);
                getLatestPalette().updateColour(id-1,color.toHexString());
                mapController.applyPalette(getLatestPalette());
                $("[id^='swatch']").css("pointer-events", "auto");
            }
        });  
       
        //Fires when an image is dropped onto the map or the info panel
        function imageReceived(e) {
            e.preventDefault();            
            var dataTransfer	= e.originalEvent.dataTransfer;
            var reader			= new FileReader();
            if (dataTransfer && dataTransfer.files.length) {      
				e.stopPropagation();
                //Using a for loop, but we will only ever have a single file
				$.each(dataTransfer.files, function (i, file) {
                    var reader = new FileReader();
                    reader.onload = $.proxy(function (file, $fileList, event) {
                        createPaletteFromImage(event.target.result)
                    }, this, file, $("#fileList"));
                    reader.readAsDataURL(file);
                });
            } else {
                var imagepath	= dataTransfer.getData('text/html');
                var imagesrc	= imagepath.match(new RegExp('src="' + '(.*)' + '"'))[1].split('"')[0];
				createPaletteFromImage(imagesrc)
            }
        }

        //Get image from manual upload or mobile input stuff
        function getImageUpload(input) {
            if (input.files && input.files[0]) {
                var reader = new FileReader();
                reader.onload = function (e) {
                    createPaletteFromImage(e.currentTarget.result)
                }
                reader.readAsDataURL(input.files[0]);
            }
        }

     
        //Events ---------------------------------------------------------------------------------------
        $("#shuffle").click(function(){
            duplicateLatestPalette();
            getLatestPalette().shuffleColours();
            mapController.applyPalette(getLatestPalette());
            updateSwatches(getLatestPalette());
        });

        $(".random").click(function(){
            createRandomPalette();
        });

        //sets the colour in the swatch editor 
        $("[id^='swatch']").click(function() {
            $("[id^='swatch']").spectrum("set", $(this).css("background"));
            $("[id^='swatch']").css("pointer-events", "none");
        });

        //When the upload button is engaged with, run the function to get the data
        $("#upload").change(function(){
            getImageUpload(this);
        });
        //When the upload button is engaged with, run the function to get the data
        $("#undo").click(function(){
            var currentPosition
            updateSwatches(getPalettePosition());
            mapController.applyPalette(paletteCollection.palettes);
            console.log(paletteCollection.palettes)
            console.log(getPalettePosition())
        });

         //Wait for an image to be dropped on the lower right UI panel...
        $('.card').on({
            'dragover dragenter': function (e) {
                e.preventDefault();
                e.stopPropagation();
            },
            'drop': function (e) {
                imageReceived(e);
            }
        });
        //...or the map itself
        $('#viewDiv').on({
            'dragover dragenter': function (e) {
                e.preventDefault();
                e.stopPropagation();
            },
            'drop': function (e) {
                imageReceived(e);
            }
        });

        

        //Logic ----------------------------------------------------------------------------------------

        initialise();

    });
@@ -2699,16 +2699,25 @@
 lection.
+palettes.
 unshift(
@@ -3155,17 +3155,17 @@
 llection
-,
+.
 palettes
@@ -6650,24 +6650,47 @@
 rentPosition
+ = getPalettePosition()
 %0A           
@@ -6705,34 +6705,31 @@
 watches(
-getPalette
+current
 Position
 ());%0A   
@@ -6720,18 +6720,18 @@
 Position
-()
++1
 );%0A     
@@ -6794,105 +6794,24 @@
 ttes
-);%0A            console.log(paletteCollection.palettes)%0A            console.log(getPalette
+%5Bcurrent
 Position
 ())%0A
@@ -6806,19 +6806,21 @@
 Position
-())
++1%5D);
 %0A       

undo stuff