void OnGUI()
        {
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, true);
            EditorGUILayout.BeginVertical(GUILayout.Width(EditorGUIUtility.currentViewWidth - 20f));
            EditorGUILayout.Space();
            GUILayout.Label("UMA AssetBundle Manager", EditorStyles.boldLabel);

            BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));

            GUILayout.Label("AssetBundle Options", EditorStyles.boldLabel);

            //Asset Bundle Encryption
            //defined here so we can modify the message if encryption settings change
            string      buildBundlesMsg     = "";
            MessageType buildBundlesMsgType = MessageType.Info;

            EditorGUI.BeginChangeCheck();
            encryptionKeysEnabled = EditorGUILayout.ToggleLeft("Enable AssetBundle Encryption", encryptionKeysEnabled);
            if (EditorGUI.EndChangeCheck())
            {
                //If encryption was turned ON generate the encryption password if necessary
                if (encryptionKeysEnabled)
                {
                    if (currentEncryptionPassword == "")
                    {
                        if (UMAABMSettings.GetEncryptionPassword() != "")
                        {
                            currentEncryptionPassword = UMAABMSettings.GetEncryptionPassword();
                        }
                        else
                        {
                            currentEncryptionPassword = EncryptionUtil.GenerateRandomPW();
                        }
                    }
                    UMAABMSettings.SetEncryptionPassword(currentEncryptionPassword);
                    buildBundlesMsg     = "You have turned on encryption and need to Rebuild your bundles to encrypt them.";
                    buildBundlesMsgType = MessageType.Warning;
                }
                else
                {
                    UMAABMSettings.DisableEncryption();
                    currentEncryptionPassword = "";
                }
            }
            if (encryptionKeysEnabled)
            {
                BeginVerticalIndented(10, new Color(0.75f, 0.875f, 1f));
                //tip
                EditorGUILayout.HelpBox("Make sure you turn on 'Use Encrypted Bundles' in the 'DynamicAssetLoader' components in your scenes.", MessageType.Info);
                //Encryption key
                //If we can work out a way for people to download a key we can use this tip and the 'EncryptionKeyURL' field
                //string encryptionKeyToolTip = "This key is used to generate the required encryption keys used when encrypting your bundles. If you change this key you will need to rebuild your bundles otherwise they wont decrypt. If you use the 'Encryption Key URL' field below you MUST ensure this field is set to the same key the url will return.";
                string encryptionKeyToolTip = "This key is used to generate the required encryption keys used when encrypting your bundles. If you change this key you will need to rebuild your bundles otherwise they wont decrypt.";
                EditorGUILayout.LabelField(new GUIContent("Bundle Encryption Password", encryptionKeyToolTip));
                EditorGUILayout.BeginHorizontal();
                if (!manualEditEncryptionKey)
                {
                    if (GUILayout.Button(new GUIContent("Edit", encryptionKeyToolTip)))
                    {
                        manualEditEncryptionKey = true;
                    }
                    EditorGUI.BeginDisabledGroup(!manualEditEncryptionKey);
                    EditorGUILayout.TextField("", UMAABMSettings.GetEncryptionPassword());                    //THis bloody field WILL NOT update when you click edit, then canel, the value stays
                    EditorGUI.EndDisabledGroup();
                }
                else
                {
                    EditorGUI.BeginChangeCheck();
                    newEncryptionPassword = EditorGUILayout.TextArea(newEncryptionPassword);
                    if (EditorGUI.EndChangeCheck())
                    {
                        encryptionSaveButEnabled = EncryptionUtil.PasswordValid(newEncryptionPassword);
                    }
                    if (encryptionSaveButEnabled)
                    {
                        if (GUILayout.Button(new GUIContent("Save"), GUILayout.MaxWidth(60)))
                        {
                            currentEncryptionPassword = newEncryptionPassword;
                            UMAABMSettings.SetEncryptionPassword(newEncryptionPassword);
                            EditorGUIUtility.keyboardControl = 0;
                            manualEditEncryptionKey          = false;
                        }
                    }
                    else
                    {
                        GUI.enabled = false;
                        if (GUILayout.Button(new GUIContent("Save", "Your Encryptiom Password should be at least 16 characters long"), GUILayout.MaxWidth(60)))
                        {
                            //Do nothing
                        }
                        GUI.enabled = true;
                    }
                    if (GUILayout.Button(new GUIContent("Cancel", "Reset to previous value: " + currentEncryptionPassword), GUILayout.MaxWidth(60)))
                    {
                        manualEditEncryptionKey          = false;
                        newEncryptionPassword            = currentEncryptionPassword = UMAABMSettings.GetEncryptionPassword();
                        encryptionSaveButEnabled         = false;
                        EditorGUIUtility.keyboardControl = 0;
                    }
                }

                EditorGUILayout.EndHorizontal();
                //EncryptionKey URL
                //not sure how this would work- the delivered key would itself need to be encrypted probably
                //Encrypted bundle suffix
                string encryptionSuffixToolTip = "This suffix is appled to the end of your encrypted bundle names when they are built. Must be lower case and alphaNumeric. Cannot be empty. Defaults to " + DEFAULT_ENCRYPTION_SUFFIX;
                EditorGUILayout.LabelField(new GUIContent("Encrypted Bundle Suffix", encryptionSuffixToolTip));
                EditorGUILayout.BeginHorizontal();
                if (!manualEditEncryptionSuffix)
                {
                    if (GUILayout.Button(new GUIContent("Edit", encryptionSuffixToolTip)))
                    {
                        manualEditEncryptionSuffix = true;
                    }
                    EditorGUI.BeginDisabledGroup(!manualEditEncryptionSuffix);
                    EditorGUILayout.TextField(new GUIContent("", encryptionSuffixToolTip), currentEncryptionSuffix);
                    EditorGUI.EndDisabledGroup();
                }
                else
                {
                    newEncryptionSuffix = EditorGUILayout.TextArea(newEncryptionSuffix);
                    if (GUILayout.Button(new GUIContent("Save")))
                    {
                        if (newEncryptionSuffix != "")
                        {
                            Regex rgx          = new Regex("[^a-zA-Z0-9 -]");
                            var   suffixToSend = rgx.Replace(newEncryptionSuffix, "");
                            currentEncryptionSuffix = suffixToSend;
                            UMAABMSettings.SetEncryptionSuffix(suffixToSend.ToLower());
                            EditorGUIUtility.keyboardControl = 0;
                            manualEditEncryptionSuffix       = false;
                        }
                    }
                }
                EditorGUILayout.EndHorizontal();

                //Encode Bundle Names
                string encodeBundleNamesTooltip = "If true encrypted bundle names will be base64 encoded";
                EditorGUI.BeginChangeCheck();
                newEncodeNamesSetting = EditorGUILayout.ToggleLeft(new GUIContent("Encode Bundle Names", encodeBundleNamesTooltip), currentEncodeNamesSetting);
                if (EditorGUI.EndChangeCheck())
                {
                    currentEncodeNamesSetting = newEncodeNamesSetting;
                    UMAABMSettings.SetEncodeNames(newEncodeNamesSetting);
                }

                EndVerticalIndented();
            }

            //Asset Bundle Building
            EditorGUILayout.Space();
            string buttonBuildAssetBundlesText = "Build AssetBundles";
            //Now defined above the encryption
            //string buildBundlesText = "Click the button below to build your bundles if you have not done so already.";
            string fullPathToBundles         = Path.Combine(Directory.GetParent(Application.dataPath).FullName, Utility.AssetBundlesOutputPath);
            string fullPathToPlatformBundles = Path.Combine(fullPathToBundles, Utility.GetPlatformName());

            //if we have not built any asset bundles there wont be anything in the cache to clear
            bool showClearCache = false;

            if (Directory.Exists(fullPathToPlatformBundles))
            {
                buttonBuildAssetBundlesText = "Rebuild AssetBundles";
                buildBundlesMsg             = buildBundlesMsg == "" ? "Rebuild your assetBundles to reflect your latest changes" : buildBundlesMsg;
                showClearCache = true;
            }
            else
            {
                buildBundlesMsg     = "You have not built your asset bundles for " + EditorUserBuildSettings.activeBuildTarget.ToString() + " yet. Click this button to build them.";
                buildBundlesMsgType = MessageType.Warning;
                showClearCache      = false;
            }
            EditorGUILayout.HelpBox(buildBundlesMsg, buildBundlesMsgType);
            if (GUILayout.Button(buttonBuildAssetBundlesText))
            {
                try
                {
                    BuildScript.BuildAssetBundles();
                    _statusMessage = "Asset Bundles Built";
                }
                catch (Exception e)
                {
                    _statusMessage = string.Format("Building Asset Bundle Exception: {0}\nStack Trace\n{1}", e.ToString(), e.StackTrace);
                    Debug.LogException(e);
                }
            }
            EndVerticalPadded(5);
            EditorGUILayout.Space();

            //Local AssetBundleServer
            BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));
            GUILayout.Label("AssetBundle Testing Server", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox("Once you have built your bundles this local Testing Server can be enabled and it will load those AssetBundles rather than the files inside the project.", MessageType.Info);

            if (!BuildScript.CanRunLocally(EditorUserBuildSettings.activeBuildTarget))
            {
                EditorGUILayout.HelpBox("Builds for " + EditorUserBuildSettings.activeBuildTarget.ToString() + " cannot access this local server, but you can still use it in the editor.", MessageType.Warning);
            }

            bool updateURL = false;

            EnableLocalAssetBundleServer = EditorGUILayout.Toggle("Start Server", EnableLocalAssetBundleServer);

            //If the server is off we need to show the user a message telling them that they will have to have uploaded their bundles to an external server
            //and that they need to set the address of that server in DynamicAssetLoader
            int newPort = Port;

            EditorGUI.BeginChangeCheck();
            newPort = EditorGUILayout.IntField("Port", Port);
            if (EditorGUI.EndChangeCheck())
            {
                if (newPort != Port)
                {
                    if (_activeHost != null && _activeHost != "")
                    {
                        ActiveHost = _activeHost.Replace(":" + Port.ToString(), ":" + newPort.ToString());
                    }
                    Port = newPort;
                    UpdateHosts();
                    //we need to start the server to see if it works with this port- regardless of whether it is turned on or not.
                    if (!EnableLocalAssetBundleServer)
                    {
                        UpdateServer(true);
                    }
                    else
                    {
                        UpdateServer();
                    }
                    if (serverException == false)
                    {
                        //We can use the set IP with this port so update it
                        if (EnableLocalAssetBundleServer)
                        {
                            SimpleWebServer.ServerURL = ActiveHost;
                        }
                    }
                    else
                    {
                        //We CANT use the set IP with this port so set the saved URL to "" and tell the user the Port is in use elsewhere
                        SimpleWebServer.ServerURL    = "";
                        EnableLocalAssetBundleServer = false;
                        portError = true;
                    }
                }
            }
            if (!EnableLocalAssetBundleServer)
            {
                if (portError)
                {
                    EditorGUILayout.HelpBox("There are no hosts available for that port. Its probably in use by another application. Try another.", MessageType.Warning);
                }
                else
                {
                    EditorGUILayout.HelpBox("When the local server is not running the game will play in Simulation Mode OR if you have set the 'RemoteServerURL' for each DynamicAssetLoader, bundles will be downloaded from that location.", MessageType.Warning);
                    if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebGL)
                    {
                        EditorGUILayout.HelpBox("WARNING: AssetBundles in WebGL builds that you run locally WILL NOT WORK unless the local server is turned on, and you build using the button below!", MessageType.Warning);
                    }
                }
            }

            EditorGUILayout.Space();

            if (_hosts != null && _hosts.Length > 0 && EnableLocalAssetBundleServer)
            {
                if (_activeHost == null || _activeHost == "")
                {
                    ActiveHost = _hosts[0];
                }
                int      activeHostInt = 0;
                string[] hostsStrings  = new string[_hosts.Length];
                for (int i = 0; i < _hosts.Length; i++)
                {
                    hostsStrings[i] = _hosts[i].Replace("http://", "").TrimEnd(new char[] { '/' });
                    if (_hosts[i] == _activeHost)
                    {
                        activeHostInt = i;
                    }
                }
                EditorGUI.BeginChangeCheck();
                int newActiveHostInt = EditorGUILayout.Popup("Host Address:  http://", activeHostInt, hostsStrings);
                if (EditorGUI.EndChangeCheck())
                {
                    if (newActiveHostInt != activeHostInt)
                    {
                        ActiveHost = _hosts[newActiveHostInt];
                        updateURL  = true;
                    }
                }
            }
            EditorGUILayout.Space();

            if (showClearCache)            //no point in showing a button for bundles that dont exist - or is there? The user might be using a remote url to download assetbundles without the localserver?
            {
                EditorGUILayout.HelpBox("You can clear the cache to force asset bundles to be redownloaded.", MessageType.Info);

                if (GUILayout.Button("Clean the Cache"))
                {
                    _statusMessage = Caching.CleanCache() ? "Cache Cleared." : "Error clearing cache.";
                }
                EditorGUILayout.Space();
            }

            EditorGUILayout.Space();
            GUILayout.Label("Server Status");
            if (_statusMessage != null)
            {
                EditorGUILayout.HelpBox(_statusMessage, MessageType.None);
            }

            if (SimpleWebServer.Instance != null)
            {
                //GUILayout.Label("Server Request Log");
                serverRequestLogOpen = EditorGUILayout.Foldout(serverRequestLogOpen, "Server Request Log");
                if (serverRequestLogOpen)
                {
                    EditorGUILayout.HelpBox(SimpleWebServer.Instance.GetLog(), MessageType.Info);
                }
            }
            if (updateURL)
            {
                SimpleWebServer.ServerURL = ActiveHost;
            }

            EndVerticalPadded(5);
            EditorGUILayout.Space();

            //Testing Build
            BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));
            GUILayout.Label("Testing Build", EditorStyles.boldLabel);
            //if the bundles are build and the server is turned on then the user can use this option otherwise there is no point
            //But we will show them that this option is available even if this is not the case
            if (!showClearCache || !EnableLocalAssetBundleServer)
            {
                EditorGUI.BeginDisabledGroup(true);
            }
            EditorGUILayout.HelpBox("Make a testing Build that uses the Local Server using the button below.", MessageType.Info);
            developmentBuild = EditorGUILayout.Toggle("Development Build", developmentBuild);
            if (GUILayout.Button("Build and Run!"))
            {
                BuildScript.BuildAndRunPlayer(developmentBuild);
            }
            if (!showClearCache || !EnableLocalAssetBundleServer)            //
            {
                EditorGUI.EndDisabledGroup();
            }
            EditorGUILayout.Space();
            EndVerticalPadded(5);

            EditorGUILayout.Space();
            //END SCROLL VIEW
            //for some reason when we build or build assetbundles when this window is open we get an error
            //InvalidOperationException: Operation is not valid due to the current state of the object
            //so try catch is here as a nasty hack to get rid of it
            try
            {
                EditorGUILayout.EndVertical();
                EditorGUILayout.EndScrollView();
            }
            catch { }
        }