using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; using Windows.Storage; namespace DrumKit.Repository { class DataRepository { #region Properties public AppSettings Settings { get; private set; } public AppInstallInfo InstallInfo { get; private set; } public ApplicationData RepositoryLocation { get; private set; } #endregion #region Constructor /// /// Creates a new instance of drumkit. /// public DataRepository() { this.InstallInfo = null; this.Settings = null; this.RepositoryLocation = null; } #endregion #region Initialize /// /// And initializes the data using that information, and sets the location. /// Note that you cannot call this method multiple times on the same instance. /// /// public async Task Initialize(ApplicationData where) { // Set up location if (this.RepositoryLocation != null) throw new InvalidOperationException("You cannot change data repository location once set."); this.RepositoryLocation = where; Log.Write("[DataRepository] Location set: {0}", where.RoamingFolder.Path); // Read installation information this.InstallInfo = await this.ReadInstallInfo(); // Version changed, or no info (new install)? if (this.IsFirstLaunch()) { // Clean up any junk await this.FactoryReset(); // Copy local assets to app data await this.InstallAssets(); // Generate "installed.xml" file await this.WriteInstallInfo(); } // Load settings this.Settings = await this.ReadSettings(); // No settings? Use default. if (this.Settings == null) this.Settings = new AppSettings(); } #endregion /// /// Reads the install info. /// /// An AppInstallInfo structure, or null if file does not exist. private async Task ReadInstallInfo() { // See if 'installed.xml' exists var files = await this.RepositoryLocation.RoamingFolder.GetFilesAsync(); StorageFile file = files.FirstOrDefault(x => x.Name == "installed.xml"); if (file == null) return null; // Read info object info = await IOHelper.DeserializeFile(file, typeof(AppInstallInfo)); return info as AppInstallInfo; } private async Task ReadSettings() { // See if 'settings.xml' exists var files = await this.RepositoryLocation.RoamingFolder.GetFilesAsync(); StorageFile file = files.FirstOrDefault(x => x.Name == "settings.xml"); if (file == null) return null; // Read info object settings = await IOHelper.DeserializeFile(file, typeof(AppSettings)); return settings as AppSettings; } private bool IsFirstLaunch() { // Get current assembly information Assembly current_asm = typeof(DataRepository).GetTypeInfo().Assembly; int version = current_asm.GetName().Version.Major * 1000 + current_asm.GetName().Version.Minor; // If no install info, this is probably first launch if (this.InstallInfo == null) { Log.Write("[DataRepository] First launch!"); return true; } // Smaller version, upgrade necessary if (this.InstallInfo.Version != version) { Log.Write("[DataRepository] Version upgrade ({0} => {1}).", this.InstallInfo.Version, version); return true; } // Nothing new return false; } /// /// Installs the assets at first launch. /// private async Task InstallAssets() { // Read content of 'ApplicationData' var reader = new Tarball.TarballReader(); await reader.Unpack(new Uri("ms-appx:///Assets/ApplicationData.tar"), this.RepositoryLocation.RoamingFolder); } /// /// Creates the 'installed.xml' file. /// private async Task WriteInstallInfo() { // Create file StorageFile file = await this.RepositoryLocation.RoamingFolder.CreateFileAsync("installed.xml"); // Create app info AppInstallInfo info = new AppInstallInfo(); // Serialize info await IOHelper.SerializeFile(file, info, typeof(AppInstallInfo)); } /// /// Resets to factory settings /// /// public async Task FactoryReset() { await this.RepositoryLocation.ClearAsync(); } /// /// Saves the current settings. /// public async Task WriteSettings() { // Get settings file var file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("settings.xml", CreationCollisionOption.ReplaceExisting); // Serialize settings await IOHelper.SerializeFile(file, this.Settings, typeof(AppSettings)); } /// /// Releases the current resources. /// public void Dispose() { } } }