/// <summary>
        /// Creates an Archival program
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="startTime"></param>
        /// <param name="archivalWindowMinutes"></param>
        /// <returns></returns>
        public async Task <IProgram> CreateArchivalProgramAsync(IChannel channel, DateTime startTime, int archivalWindowMinutes = 60, int overlappingArchivalWindowMinutes = 2)
        {
            // First segment Archival Program (the one that records in the background for VOD playback)
            var archivalProgram_StartTime          = startTime;
            var archivalProgram_ArchivalWindow     = TimeSpan.FromMinutes(archivalWindowMinutes);
            var archivalProgram_EndTime            = archivalProgram_StartTime.Add(archivalProgram_ArchivalWindow).AddMinutes(-1 * overlappingArchivalWindowMinutes);
            var archivalProgram_programName        = NamingHelpers.GetArchivingProgramName(archivalProgram_StartTime);
            var archivalProgram_programDescription = NamingHelpers.GetArchivingProgramDescription(channel.Name, archivalProgram_StartTime, archivalProgram_EndTime);

            // Create the Archiving Program
            return(await CreateProgramIfNotExistsAsync(channel, archivalProgram_programName, archivalProgram_programDescription, archivalProgram_ArchivalWindow));
        }
        /// <summary>
        /// Creates the DefaultProgram
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="archivalWindowMinutes"></param>
        /// <returns></returns>
        public async Task <IProgram> CreateDefaultProgramIfNotExistsAsync(IChannel channel, int archivalWindowMinutes = 360)
        {
            // Default Program details (the one that keeps on running without us touching it)
            var defaultProgram_StartTime          = DateTime.UtcNow;
            var defaultProgram_ArchivalWindow     = TimeSpan.FromMinutes(archivalWindowMinutes);
            var defaultProgram_EndTime            = defaultProgram_StartTime.Add(defaultProgram_ArchivalWindow);
            var defaultProgram_programName        = NamingHelpers.GetDefaultProgramName(channel.Name);;
            var defaultProgram_programDescription = NamingHelpers.GetDefaultProgramDescription(channel.Name);

            // Create DefaultProgram
            return(await CreateProgramIfNotExistsAsync(channel, defaultProgram_programName, defaultProgram_programDescription, defaultProgram_ArchivalWindow));
        }
        /// <summary>
        /// Creates a Program
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="name"></param>
        /// <param name="description"></param>
        /// <param name="archiveWindowLength"></param>
        /// <returns></returns>
        public async Task <IProgram> CreateProgramIfNotExistsAsync(IChannel channel, string name, string description, TimeSpan archiveWindowLength)
        {
            System.Diagnostics.Trace.TraceInformation("Creating Program [{0}] for Channel ID [{1}] with Archival Window [{2}] minutes", name, channel.Id, archiveWindowLength.TotalMinutes);

            IProgram program;
            IAsset   asset;
            ILocator locator;
            var      assetName = NamingHelpers.GetArchivingAssetName(channel.Name, name);

            // Try to find an asset with this name
            System.Diagnostics.Trace.TraceInformation("Trying to find existing Archiving asset [{0}]", assetName);

            asset = GetAssetByName(assetName);

            if (asset == null)
            {
                System.Diagnostics.Trace.TraceInformation("Archiving asset [{0}] doesn't exist. Create it.", assetName);
                // Create output asset for the program (archive)
                asset = CloudMediaContext.Assets.Create(assetName, AssetCreationOptions.None);
                System.Diagnostics.Trace.TraceInformation("Archiving asset [{0}] Created [{1}]", assetName, asset.Id);
            }

            // Try to find this program first before creating it
            System.Diagnostics.Trace.TraceInformation("Trying to find existing Program [{0}]", name);
            program = GetProgramByName(channel, name);

            if (program == null)
            {
                System.Diagnostics.Trace.TraceInformation("Program [{0}] doesn't exist. Create it.", name);
                // Add program to Azure Media Service channel
                program = await channel.Programs.CreateAsync(
                    new ProgramCreationOptions
                {
                    Name                = name,
                    Description         = description,
                    ArchiveWindowLength = archiveWindowLength,
                    AssetId             = asset.Id
                });

                System.Diagnostics.Trace.TraceInformation("Program [{0}] Created [{1}]", name, program.Id);
            }

            // Start the Program if it isn't already running
            System.Diagnostics.Trace.TraceInformation("Start Program [{0}] if it isn't running", name);
            if (program.State != ProgramState.Starting || program.State != ProgramState.Running)
            {
                await program.StartAsync();
            }

            // Create (or retrieve access policy)
            System.Diagnostics.Trace.TraceInformation("Get Access Policy [{0}]", "100 years Read Access Policy");
            var accessPolicy = GetAccessPolicy("100 years Read Access Policy");

            if (accessPolicy == null)
            {
                System.Diagnostics.Trace.TraceInformation("Access Policy [{0}] doesn't exist. Create it.", "100 years Read Access Policy");
                accessPolicy = await CreateAccessPolicyAsync("100 years Access Policy", TimeSpan.FromDays(3650));

                System.Diagnostics.Trace.TraceInformation("Access Policy [{0}] Created [{1}]", accessPolicy.Name, accessPolicy.Id);
            }
            // Try to find a Locator for the asset before creating it
            System.Diagnostics.Trace.TraceInformation("Finding OnDemandOrigin Locator for Asset ID [{0}]", asset.Id);
            locator = GetLocator(asset.Id, LocatorType.OnDemandOrigin);

            if (locator == null)
            {
                System.Diagnostics.Trace.TraceInformation("Locator for Asset ID [{0}] doesn't exist. Create it.", asset.Id);

                // Create a locator for the Asset in the Program
                locator = await CloudMediaContext.Locators.CreateLocatorAsync
                          (
                    LocatorType.OnDemandOrigin,
                    asset,
                    accessPolicy
                          );

                System.Diagnostics.Trace.TraceInformation("Locator for Asset ID [{0}] Created [{1}].", asset.Id, locator.Id);
            }

            // Return program
            return(program);
        }