@using Core.Calculation
@using Microsoft.EntityFrameworkCore
@page "/meeting-schedule/scheduler"
@inject IConfiguration Configuration
@inject AppDbContext Context

<PageTitle>@Configuration["ChapterSettings:Shortname"] TSA Schedule @Configuration["ChapterSettings:CompetitionYear"]</PageTitle>

<MudText Typo="Typo.h3">@Configuration["ChapterSettings:Shortname"] TSA Schedule @Configuration["ChapterSettings:CompetitionYear"]</MudText>


<MudPaper Class="pa-4 mt-5">
    <MudGrid>
        <MudItem Style="width:160px;">
            <MudNumericField @bind-Value="_parameters.TimeSlots"
                             Label="Time Slots" Min="1" Max="4"></MudNumericField>
        </MudItem>
        <TeamSelector Teams="@_teams" SelectedTeams="@_requiredTeams" Label="Required"></TeamSelector>
        <MudButton OnClick="() => RequireRegionals()">Require Regionals</MudButton>
        
    </MudGrid>
    <MudButton Class="ma-3" OnClick="Solve" Variant="Variant.Filled" Color="Color.Primary" Disabled="@_isSolving">Solve</MudButton>
</MudPaper>


<MudItem xs="12" lg="4">
<MudText Typo="Typo.h4">Time Slots</MudText>
    <MudTable T="Team[]" ServerData="SolveSchedule" @ref="_solutionData">
        <HeaderContent>

        </HeaderContent>
        <RowTemplate>
            <MudTd>
                @{
                    var ol = TeamSchedulerSolution.GetStudentTeamOverlaps(context);}
                @foreach (var t in context)
                {
                    <MudItem>
                        @t.ToString() -
                        @string.Join(", ", t.Students.Select(s => s.FirstName + " " + (ol.Any(o => o.Item1.Equals(s)) ? "*" : "" )) )
                    </MudItem>
                }
                @* @foreach (var overlap in ol)
                {
                    <MudItem>
                        @string.Join(", ", overlap.Item1)
                    </MudItem>
                } *@
                
                @{ var notInTimeSLot = TeamSchedulerSolution.GetStudentsNotInTimSlot(context, _students); }
                @if (notInTimeSLot.Any()) {
                    <MudItem>
                        <i>
                            Not scheduled: @string.Join(", ", notInTimeSLot.Select(s => s.FirstName))
                        </i>
                    </MudItem>
                }

            </MudTd>
        </RowTemplate>
</MudTable>
</MudItem>

@code {
    private Team[]? _teams;
    private Student[]? _students;
    MudTable<Team[]> _solutionData;
    private TeamSchedulerSolution _solution;
    private TeamSchedulerOptions _parameters;
    bool _isSolving = false;
    private HashSet<Team> _requiredTeams = [];

    private void RequireRegionals()
    {
        foreach (var team in _teams.Where(e => e.Event.RegionalEvent))
        {
            _requiredTeams.Add(team);
        }
    }

    protected override async Task OnInitializedAsync()
    {
        _parameters =
            new TeamSchedulerOptions(
                timeSlots: 4,
                mustIncludeEvents:
                [
                // "Medical Technology", "Electrical Applications"  , "RegionalTeam",
                // ,"Dragster", "Flight"
                ],
                extended:
                [
                // "Invention", "Construction Challenge",  "Mechanical", "Mass", "Micro"
                //"STEM"
                //"Community", "Vlogging"// "Microcontroller"
                ],
                omittedEvents:
                [
                // "Vlogging", "Junior", "Community Service Video", "Digital Photography",
                // "STEM"

                //"Leadership",// "Electrical", //"Construction"
                // "Forensic",
                //"CAD"
                //"I&I Team 1", "I&I Team 2"//, "Website Design",
                ],
                absentStudents:
                [
                ]
            );


        _teams
                = await Context.Teams
                    .Include(e => e.Event)
                    .Include(e => e.Students)
                    .OrderBy(e => e.Event.Name)
                    .ThenBy(e => e.Identifier)
                    .ToArrayAsync();

        _students = 
            await Context.Students
                .Include(e => e.Teams)
                .ThenInclude(e => e.Captain)
                .Include(e => e.EventRankings)
                .ThenInclude(e => e.EventDefinition)
                .OrderBy(e => e.FirstName).ToArrayAsync();
    }

    private async Task<TableData<Team[]>> SolveSchedule(TableState arg1, CancellationToken arg2)
    {
        //_isSolving = true;

       

        var requiredTeams = _teams;

        var teamScheduler = new TeamScheduler(_requiredTeams, _parameters.TimeSlots);
        
        // teamScheduler
        //     .ScheduleSeparate(
        //         _teams.First(e => e.Event.Name.Contains("Data Science")),
        //         _teams.First(e => e.Event.Name.Contains("Microcontroller Design"))
        //         );

        _solution = teamScheduler.Solve();

        await InvokeAsync(StateHasChanged); // let the UI know that the solution has been found

        return new TableData<Team[]> { Items = _solution.TimeSlots};
    }


    private void Solve()
    {
        _solutionData.ReloadServerData();
    }
}
