// Copyright Epic Games, Inc. All Rights Reserved.
using HordeServer.Models;
using HordeServer.Services;
using HordeServer.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using TimeZoneConverter;
namespace HordeServer.Controllers
{
///
/// Controller for the /api/v1/status endpoint
///
[ApiController]
[Authorize]
[Route("[controller]")]
public class NoticesController : ControllerBase
{
///
/// Timezone to use for display notices
///
TimeZoneInfo TimeZone;
///
/// The globals singleton
///
ISingletonDocument Globals;
///
/// Constructor
///
/// The server settings
/// The globals singleton
public NoticesController(IOptions Settings, ISingletonDocument Globals)
{
string? ScheduleTimeZone = Settings.Value.ScheduleTimeZone;
this.TimeZone = (ScheduleTimeZone == null) ? TimeZoneInfo.Local : TZConvert.GetTimeZoneInfo(ScheduleTimeZone);
this.Globals = Globals;
}
///
/// Update a status message
///
///
///
[HttpPost("/api/v1/notices")]
public async Task AddNoticeAsync(Notice Status)
{
Status.Id = ObjectId.GenerateNewId().ToString();
await Globals.UpdateAsync(x => x.Notices.Add(Status));
return Ok();
}
///
/// Remove a manually added status message
///
///
[HttpDelete("/api/v1/notices/{Id}")]
public async Task DeleteNoticeAsync(string Id)
{
await Globals.UpdateAsync(x => x.Notices.RemoveAll(x => x.Id == Id));
return Ok();
}
///
/// Gets the current status messages
///
/// The status messages
[HttpGet("/api/v1/notices")]
public async Task> GetNoticesAsync()
{
Globals Value = await Globals.GetAsync();
List Messages = new List(Value.Notices);
if(Value.ScheduledDowntime.Count > 0)
{
DateTimeOffset Now = DateTimeOffset.Now;
(DateTimeOffset StartTime, DateTimeOffset FinishTime) = Value.ScheduledDowntime[0].GetNext(Now);
for (int Idx = 1; Idx < Value.ScheduledDowntime.Count; Idx++)
{
(DateTimeOffset NextStartTime, DateTimeOffset NextFinishTime) = Value.ScheduledDowntime[Idx].GetNext(Now);
if (NextFinishTime < StartTime)
{
StartTime = NextStartTime;
}
if (NextStartTime < FinishTime && NextFinishTime > FinishTime)
{
FinishTime = NextFinishTime;
}
}
if (StartTime < Now)
{
string FinishTimeString = String.Format(CultureInfo.CurrentCulture, "{0:t}", TimeZoneInfo.ConvertTime(FinishTime, TimeZone));
Messages.Add(new Notice { StartTime = StartTime.UtcDateTime, FinishTime = FinishTime.UtcDateTime, Message = $"Horde is currently in scheduled downtime. Jobs will resume execution at {FinishTimeString} {TimeZone.Id}." });
}
else if(StartTime < Now + TimeSpan.FromHours(12.0))
{
string StartTimeString = String.Format(CultureInfo.CurrentCulture, "{0:t}", StartTime);
string FinishTimeString = String.Format(CultureInfo.CurrentCulture, "{0:t}", FinishTime);
Messages.Add(new Notice { StartTime = StartTime.UtcDateTime, FinishTime = FinishTime.UtcDateTime, Message = $"Downtime is scheduled from {StartTimeString} to {FinishTimeString} {TimeZone.Id}. No jobs will run during this time." });
}
}
return Messages;
}
}
}