Inheritance: XmlObjectRoot, IProject
        public static void CheckProgram(XmlProgram program)
        {
            const int moleIndex = 2;


            var foreverBegin = program.SpriteList.Sprites[moleIndex].Scripts.Scripts[0].Bricks.Bricks.FirstOrDefault(
                a => a is XmlForeverBrick) as XmlForeverBrick;
            var foreverEnd = program.SpriteList.Sprites[moleIndex].Scripts.Scripts[0].Bricks.Bricks.FirstOrDefault(
                a => a is XmlForeverLoopEndBrick) as XmlForeverLoopEndBrick;

            if (foreverBegin == null)
                Debugger.Break();

            if (foreverEnd == null)
                Debugger.Break();
        }
        public void XmlSpriteReferencesTest()
        {
            XmlProgram programm = new XmlProgram()
            {
                SpriteList = new XmlSpriteList()
                {
                    Sprites = new List<XmlSprite>(),
                },
                VariableList = new XmlVariableList()
                {
                    ObjectVariableList = new XmlObjectVariableList()
                    {
                        ObjectVariableEntries = new List<XmlObjectVariableEntry>(),
                    }
                }
            };

            programm.SpriteList.Sprites.Add(new XmlSprite());
            programm.SpriteList.Sprites.Add(new XmlSprite());

            programm.VariableList.ObjectVariableList.ObjectVariableEntries.Add(new XmlObjectVariableEntry());
            programm.VariableList.ObjectVariableList.ObjectVariableEntries.Add(new XmlObjectVariableEntry());

            XmlParserTempProjectHelper.Program = programm;


            programm.VariableList.ObjectVariableList.ObjectVariableEntries[0].Sprite = programm.SpriteList.Sprites[0];
            programm.VariableList.ObjectVariableList.ObjectVariableEntries[1].Sprite = programm.SpriteList.Sprites[1];

            var referenceObject = "<object reference=\"../../../../objectList/object[2]\" />";
            var testObject =
                programm.VariableList.ObjectVariableList.ObjectVariableEntries[1].XmlSpriteReference.CreateXml()
                    .ToString();

            Assert.AreEqual(referenceObject, testObject);
        }
        public async Task LoadSampleProgram()
        {
            using (var storage = StorageSystem.GetStorage())
            {
                await storage.DeleteDirectoryAsync("");
            }

            foreach (KeyValuePair<string, string> pair in _sampleProjectNames)
            {
                var projectFileName = pair.Key;
                var projectName = pair.Value;
                var resourcePath = string.Format("SamplePrograms/{0}", projectFileName);

                Stream resourceStream = null;

                try
                {
                    var resourceLoader = ServiceLocator.ResourceLoaderFactory.CreateResourceLoader();
                    resourceStream = await resourceLoader.OpenResourceStreamAsync(ResourceScope.Resources, resourcePath);
                    

                    if (resourceStream != null)
                    {
                        var projectFolderPath = Path.Combine(StorageConstants.ProgramsPath, projectName);

                        using (var storage = StorageSystem.GetStorage())
                        {
                            if (!await storage.DirectoryExistsAsync(projectFolderPath))
                            {
                                await ServiceLocator.ZipService.UnzipCatrobatPackageIntoIsolatedStorage(resourceStream, StorageConstants.ProgramsPath + "/" + projectName);
                            }
                        }

                        using (var storage = StorageSystem.GetStorage())
                        {
                            var textFilePath = Path.Combine(StorageConstants.ProgramsPath, projectName, StorageConstants.ProgramCodePath);
                            var xml = await storage.ReadTextFileAsync(textFilePath);

                            var xmlProgram = new XmlProgram(xml)
                            {
                                ProgramHeader = {ProgramName = projectName}
                            };


                            var path = Path.Combine(StorageConstants.ProgramsPath,
                                projectFileName, StorageConstants.ProgramCodePath);
                            var xmlString = xmlProgram.ToXmlString();
                            await storage.WriteTextFileAsync(path, xmlString);
                        }
                    }
                }
                catch (Exception)
                {
                    Debugger.Break(); // sample project does not exist: please remove from _sampleProjectNames or add to Core/Resources/SamplePrograms
                }
                finally
                {
                    if (resourceStream != null)
                    {
                        resourceStream.Dispose();
                    }
                }
            }
        }
        public void XmlObjectUservariableReferenceTest()
        {
            XmlProgram programm = new XmlProgram()
            {
                SpriteList = new XmlSpriteList()
                {
                    Sprites = new List<XmlSprite>(),
                },
                VariableList = new XmlVariableList()
                {
                    ObjectVariableList = new XmlObjectVariableList()
                    {

                    }
                }
            };

            TextReader sr = new StringReader("<objectList>" +
                                            "  <object name=\"Hintergrund\">" +
                                            "  </object>" +
                                            "  <object name=\"FlaPacMan\">" +
                                            "  <scriptList>" +
                                            "	<script type=\"BroadcastScript\">" +
                                            "     <brickList>" +
                                            "		<brick type=\"SetVariableBrick\">" +
                                            "            <formulaList>" +
                                            "              <formula category=\"VARIABLE\">" +
                                            "                <type>NUMBER</type>" +
                                            "                <value>1</value>" +
                                            "              </formula>" +
                                            "            </formulaList>" +
                                            "            <userVariable>paclives</userVariable>" +
                                            "          </brick>" +
                                            "          <brick type=\"SetVariableBrick\">" +
                                            "            <formulaList>" +
                                            "              <formula category=\"VARIABLE\">" +
                                            "                <type>NUMBER</type>" +
                                            "                <value>0.0</value>" +
                                            "              </formula>" +
                                            "            </formulaList>" +
                                            "            <userVariable>change anim</userVariable>" +
                                            "          </brick>" +
                                            "          <brick type=\"SetVariableBrick\">" +
                                            "            <formulaList>" +
                                            "              <formula category=\"VARIABLE\">" +
                                            "                <type>NUMBER</type>" +
                                            "                <value>1</value>" +
                                            "              </formula>" +
                                            "            </formulaList>" +
                                            "            <userVariable>animframe</userVariable>" +
                                            "          </brick>" +
                                            "       </brickList>" +
                                            "     </script>" +
                                            "   </scriptList>" +
                                            "  </object>" +
                                            "  <object name =\"handmade referenceobject\">" +
                                            "  <scriptList>" +
                                            "	<script type=\"BroadcastScript\">" +
                                            "     <brickList>" +
                                            "       <brick type =\"ChangeVariableBrick\">" +
                                            "            <formulaList>" +
                                            "              <formula category=\"VARIABLE_CHANGE\">" +
                                            "                <type>NUMBER</type>" +
                                            "                <value>7</value>" +
                                            "              </formula>" +
                                            "            </formulaList>" +
                                            "            <userVariable reference=\"../../../../../../object[2]/scriptList/script/brickList/brick[3]/userVariable\" />" +
                                            "       </brick>" +
                                            "      </brickList > " +
                                            "     </script>" +
                                            "   </scriptList>" +
                                            "  </object>" + 
                                            "</objectList>");
            var objectList = XElement.Load(sr);

            programm.SpriteList.LoadFromXml(objectList);
            
            XmlParserTempProjectHelper.Program = programm;

            //change these 3 to get differnt deep references as you are specifying the "iterator" in the imaginary XML-Docucment
            XmlParserTempProjectHelper.currentObjectNum = 3; 
            XmlParserTempProjectHelper.currentBrickNum = 1;
            XmlParserTempProjectHelper.currentVariableNum = 1;

            //the variable you wanna reference to from the position of the "iterator"  - ! it has to exist in the above XML-snippet but you can also modify this if you know what you are doing! 
            var userVariableRefTest = new XmlUserVariableReference(); 
            userVariableRefTest.UserVariable = ((XmlSetVariableBrick) programm.SpriteList.Sprites[1].Scripts.Scripts[0].Bricks.Bricks[2]).UserVariable;
            userVariableRefTest.UserVariable.ObjectNum = 2;
            userVariableRefTest.UserVariable.ScriptNum = 1;
            userVariableRefTest.UserVariable.BrickNum = 3;
            userVariableRefTest.UserVariable.VariableNum = 1;

            String testString = userVariableRefTest.CreateXml().ToString();

            //string of variable reference from xml-snippet
            //be in mind to adapt the deep accordingly to your changes above
            //if you change the refence be in mind that in the Catrobat XML language (at leats until 0.94) counting starts at 1 not at 0 and [1]'s are not shown/written 
            var referenceXElement = objectList.Descendants(XmlConstants.UserVariable).Where(uservar => uservar.HasAttributes).First();
            String referenceString = referenceXElement.ToString();//should be "<userVariable reference=\"../../../../../../object[2]/scriptList/script/brickList/brick[3]/userVariable\" />";
            Assert.AreEqual(referenceString, testString, "XmlObjectUservariableReferenceTest failed at the CreateXML part");

            var userVariableRefLoaded = new XmlUserVariableReference();
            userVariableRefLoaded.LoadFromXml(referenceXElement);
            userVariableRefLoaded.UserVariable.ObjectNum = 2;
            userVariableRefLoaded.UserVariable.ScriptNum = 1;
            userVariableRefLoaded.UserVariable.BrickNum = 3;
            userVariableRefLoaded.UserVariable.VariableNum = 1;

            Assert.AreEqual(userVariableRefLoaded.UserVariable, userVariableRefTest.UserVariable, "XmlObjectUservariableReferenceTest failed at the LoadXML part");
            


        }
        public void UpdateProgramHeader(XmlProgram program)
        {
            program.ProgramHeader.ApplicationBuildName = ServiceLocator.
                SystemInformationService.CurrentApplicationBuildName;

            program.ProgramHeader.ApplicationBuildNumber = ServiceLocator.
                SystemInformationService.CurrentApplicationBulidNumber;

            program.ProgramHeader.ApplicationName = XmlConstants.ApplicationName;

            program.ProgramHeader.ApplicationVersion = ServiceLocator.
                SystemInformationService.CurrentApplicationVersion;

            program.ProgramHeader.CatrobatLanguageVersion = XmlConstants.TargetIDEVersion;

            program.ProgramHeader.DeviceName = ServiceLocator.
                SystemInformationService.DeviceName;

            program.ProgramHeader.Platform = ServiceLocator.
                SystemInformationService.PlatformName;

            program.ProgramHeader.PlatformVersion = ServiceLocator.
                SystemInformationService.PlatformVersion;

            program.ProgramHeader.ScreenWidth = ServiceLocator.
                SystemInformationService.ScreenWidth * ServiceLocator.
                SystemInformationService.ScaleFactor;

            program.ProgramHeader.ScreenHeight = ServiceLocator.
                SystemInformationService.ScreenHeight * ServiceLocator.
                SystemInformationService.ScaleFactor;
            
            // TODO: check if and how the following properties should be set
            //program.ProjectHeader.DateTimeUpload = "";
            //program.ProjectHeader.ProgramLicense = "";
            //program.ProjectHeader.MediaLicense = "";
            //program.ProjectHeader.ScreenHeight = "";
            //program.ProjectHeader.ScreenWidth = "";
            //program.ProjectHeader.Tags = "";
        }
        public async Task<Program> CopyProgram(string sourceProgramName,
            string newProgramName)
        {
            using (var storage = StorageSystem.GetStorage())
            {
                var sourcePath = Path.Combine(StorageConstants.ProgramsPath, sourceProgramName);
                var destinationPath = Path.Combine(StorageConstants.ProgramsPath, newProgramName);

                var counter = 1;
                while (await storage.DirectoryExistsAsync(destinationPath))
                {
                    newProgramName = newProgramName + counter;
                    destinationPath = Path.Combine(StorageConstants.ProgramsPath, newProgramName);
                    counter++;
                }

                await storage.CopyDirectoryAsync(sourcePath, destinationPath);

                var tempXmlPath = Path.Combine(destinationPath, StorageConstants.ProgramCodePath);
                var xml = await storage.ReadTextFileAsync(tempXmlPath);
                var xmlProgram = new XmlProgram(xml)
                {
                    ProgramHeader = {ProgramName = newProgramName}
                };

                var path = Path.Combine(StorageConstants.ProgramsPath, 
                    newProgramName, StorageConstants.ProgramCodePath);
                var programConverter = new ProgramConverter();
                var program = programConverter.Convert(xmlProgram);

                var xmlString = xmlProgram.ToXmlString();
                await storage.WriteTextFileAsync(path, xmlString);
                
                return program;
            }
        }
        public async Task<CheckProgramResult> CheckProgram(string pathToProgramDirectory)
        {
            var pathToProgramCodeFile = Path.Combine(pathToProgramDirectory, StorageConstants.ProgramCodePath);

            XmlProgram convertedProgram = null;
            var checkResult = new CheckProgramResult();
            PortableImage programScreenshot = null;
            string programName = null;
            string programCode = null;

            using (var storage = StorageSystem.GetStorage())
            {
                programScreenshot =
                    await storage.LoadImageAsync(Path.Combine(
                    pathToProgramDirectory,
                    StorageConstants.ProgramManualScreenshotPath)) ??
                    await storage.LoadImageAsync(Path.Combine(
                    pathToProgramDirectory,
                    StorageConstants.ProgramAutomaticScreenshotPath));

                if (!await storage.FileExistsAsync(pathToProgramCodeFile))
                {
                    checkResult.State = ProgramState.FilesMissing;
                    return checkResult;
                }
                programCode = await storage.ReadTextFileAsync(pathToProgramCodeFile);                
            }

            var converterResult = await CatrobatVersionConverter.
                ConvertToXmlVersion(programCode, XmlConstants.TargetIDEVersion);

            if (converterResult.Error != CatrobatVersionConverter.VersionConverterStatus.NoError)
            {
                switch (converterResult.Error)
                {
                    case CatrobatVersionConverter.VersionConverterStatus.VersionTooNew:
                        checkResult.State = ProgramState.VersionTooNew;
                        break;
                    case CatrobatVersionConverter.VersionConverterStatus.VersionTooOld:
                        checkResult.State = ProgramState.VersionTooOld;
                        break;
                    default:
                        checkResult.State = ProgramState.Damaged;
                        break;
                }
                return checkResult;
            }

            try
            {
                convertedProgram = new XmlProgram(converterResult.Xml);
                programName = convertedProgram.ProgramHeader.ProgramName;
            }
            catch (Exception)
            {
                checkResult.State = ProgramState.Damaged;
                checkResult.ProgramHeader = null;
                checkResult.Program = null;
                return checkResult;
            }

            try
            {
                ProgramConverter programConverter = new ProgramConverter();
                checkResult.Program = programConverter.Convert(convertedProgram);
                NativeWrapper.SetProject(convertedProgram);
            }
            catch (Exception)
            {
                checkResult.State = ProgramState.ErrorInThisApp;
                checkResult.ProgramHeader = null;
                checkResult.Program = null;
                return checkResult;
            }

            if(programName == null)
                programName = XmlProgramHelper.GetProgramName(converterResult.Xml);

            checkResult.ProgramHeader = new LocalProgramHeader
            {
                Screenshot = programScreenshot,
                ProjectName = programName,
            };

            checkResult.State = ProgramState.Valid;
            return checkResult;
        }