@using Radzen
@using Radzen.Blazor.Rendering

@typeparam TValue
@inherits RadzenComponent
@implements IRadzenFormComponent
@if (Visible)
{
    <div @ref="@Element" @attributes="Attributes" class="@GetCssClass()" style="@GetStyle()" id="@GetId()">
        @if (!Inline)
        {
            @if (ShowInput || !ShowButton)
            {
                @if (Immediate)
                {
                    <input @ref="@input" @attributes="InputAttributes" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
                            @onchange="@ParseDate" @oninput="@ParseDateImmediate" autocomplete="off" type="text" name="@Name" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation="stopKeydownPropagation"
                           class="rz-inputtext @InputClass @(ReadOnly ? "rz-readonly" : "") @(!ShowButton ? "rz-input-trigger" : "")" id="@Name" placeholder="@CurrentPlaceholder" />
                }
                else
                {
                    <input @ref="@input" @attributes="InputAttributes" disabled="@Disabled" readonly="@IsReadonly" value="@FormattedValue" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
                            @onchange="@ParseDate" autocomplete="off" type="text" name="@Name" @onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation="stopKeydownPropagation"
                           class="rz-inputtext @InputClass @(ReadOnly ? "rz-readonly" : "") @(!ShowButton ? "rz-input-trigger" : "")" id="@Name" placeholder="@CurrentPlaceholder" />
                }
            }
            @if (ShowButton)
            {
                <button aria-label="@ToggleAriaLabel" aria-haspopup="dialog" aria-controls="@PopupID" aria-expanded="false"
                        @onmousedown=@OnToggle class="@($"rz-datepicker-trigger{(ShowInput ? " rz-datepicker-field-button" : "")} rz-button rz-button-icon-only{(Disabled ? " rz-state-disabled" : "")} {ButtonClass}")" tabindex="-1" type="button">
                    <span aria-hidden="true" class="@ButtonClasses"></span><span class="rz-button-text"></span>
                </button>
            }
            @if (AllowClear && HasValue && (ShowInput || !ShowButton))
            {
                <button type="button" class="notranslate rz-dropdown-clear-icon rzi rzi-times" aria-label="@ClearAriaLabel" @onclick="@Clear" @onclick:stopPropagation="true"></button>
            }
        }

        <RadzenPopup id="@PopupID" Lazy=@(PopupRenderMode == PopupRenderMode.OnDemand) @ref=@popup style=@PopupStyle
               Close="@OnPopupCloseFromEvent"
               role="dialog" aria-label="@PopupAriaLabel"
               class="@($"{(Inline ? "rz-datepicker-inline-container " : "rz-datepicker-popup-container ")}")">
                <div class="rz-calendar" @onkeydown="@OnPopupKeyDown">
                    @if (!TimeOnly)
                    {
                        <div class="rz-calendar-header">
                            <button id="@(GetId() + "pm")" type="button" tabindex="-1" aria-label="@PrevMonthAriaLabel" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-prev" @onclick="@(() => { if (!Disabled) { try { var prev = Culture.Calendar.AddMonths(CurrentDate, -1); if(GetCalendarYear(prev) >= YearFrom) {CurrentDate = prev;}} catch (ArgumentOutOfRangeException) {}} })" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
                                <span class="notranslate rzi rz-calendar-prev-icon"></span>
                            </button>
                            <button id="@(GetId() + "nm")" type="button" tabindex="-1" aria-label="@NextMonthAriaLabel" class="rz-button rz-button-md rz-variant-text rz-button-icon-only rz-secondary rz-shade-default rz-calendar-next" @onclick="@(() => { if (!Disabled) { try { var next = Culture.Calendar.AddMonths(CurrentDate, 1); if(GetCalendarYear(next) <= YearTo) {CurrentDate = next;}} catch (ArgumentOutOfRangeException) {} } })" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
                                <span class="notranslate rzi rz-calendar-next-icon"></span>
                            </button>
                            <div class="rz-calendar-title">
                                <RadzenDropDown @ref="monthDropDown" class="rz-calendar-month-dropdown" TabIndex="@TabIndex"
                                                TValue="int" Value="@GetCalendarMonth(CurrentDate)" Disabled="@Disabled" Data="@months" TextProperty="Name" ValueProperty="Value"
                                                Change="@((args) => { var argStr = args?.ToString(); if (!string.IsNullOrEmpty(argStr)) SetMonth(int.Parse(argStr!)); })"/>
                                <RadzenDropDown @ref="yearDropDown" class="rz-calendar-year-dropdown" TabIndex="@TabIndex"
                                                TValue="int" Value="@GetCalendarYear(CurrentDate)" Disabled="@Disabled" Data="@years" TextProperty="Name" ValueProperty="Value"
                                                Change="@((args) => { var argStr = args?.ToString(); if (!string.IsNullOrEmpty(argStr)) SetYear(int.Parse(argStr!)); })" />
                            </div>
                        </div>
                        @if(ShowDays)
                        {
                        <div class="rz-calendar-view-container">
                            <table class="rz-calendar-view rz-calendar-month-view" style="@(Inline ? "" : "width:100%")"
                                   role="grid" aria-label="@GetCalendarAriaLabel()">
                                <thead>
                                    <tr role="row">
                                        @if (ShowCalendarWeek)
                                        {
                                            <th scope="col" role="columnheader" class="rz-datepicker-week-number">
                                                <span>@CalendarWeekTitle</span>
                                            </th>
                                        }
                                        @foreach (var day in ShiftedDayNames)
                                        {
                                            <th scope="col" role="columnheader" abbr="@day.Full" aria-label="@day.Full">
                                                <span aria-hidden="true">@day.Abbreviated</span>
                                            </th>
                                        }
                                    </tr>
                                </thead>
                                <tbody>
                                    @{
                                        int dayNumber = 0;
                                    }
                                    @for (int i = 0; i < 6; i++)
                                    {
                                        <tr role="row">
                                            @if (ShowCalendarWeek)
                                            {
                                                <td class="rz-calendar-other-month rz-calendar-week-number">@Culture.Calendar.GetWeekOfYear(StartDate.AddDays(i * 7), Culture.DateTimeFormat.CalendarWeekRule, Culture.DateTimeFormat.FirstDayOfWeek)</td>
                                            }
                                            @for (int j = 0; j < 7; j++)
                                            {
                                                @if((DateTime.MaxValue - StartDate).TotalDays <= dayNumber)
                                                {
                                                    break;
                                                }

                                                DateTime date = StartDate.AddDays(dayNumber++);
                                                var dateArgs = DateAttributes(date);
                                                var isFocused = FocusedDate.Date == date.Date;
                                                var cellDisabled = Disabled || dateArgs.Disabled;

                                                <td @attributes="@(dateArgs.Attributes)" class="@GetDayCssClass(date, dateArgs)"
                                                    id="@GetDayCellId(date)"
                                                    role="gridcell"
                                                    tabindex="@(isFocused && !cellDisabled ? "0" : "-1")"
                                                    aria-label="@GetDayAriaLabel(date, dateArgs)"
                                                    aria-selected="@(IsDateSelected(date) ? "true" : "false")"
                                                    aria-disabled="@(dateArgs.Disabled ? "true" : null)"
                                                    @onclick="@(async () => { if (!Disabled && !dateArgs.Disabled) { await SetDay(date); } })"
                                                    @onkeydown="@(args => OnDayKeyDown(args, date, dateArgs))"
                                                    @onkeydown:preventDefault="preventKeyPress"
                                                    @onkeydown:stopPropagation="stopKeydownPropagation">
                                                    <span class=@GetDayCssClass(date, dateArgs, false)>@GetCalendarDayOfMonth(date)</span>
                                                </td>
                                            }
                                        </tr>
                                    }
                                </tbody>
                            </table>
                        </div>
                        }
                        @if (FooterTemplate != null)
                        {
                            <div class="rz-datepicker-footer">
                                 @FooterTemplate
                            </div>
                        }
                    }
                </div>
                @if (ShowTime)
                {
                <div class="rz-timepicker" @onmousedown:stopPropagation>
                        @if (ShowHour)
                        {
                        <RadzenNumeric @ref="hourNumeric" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", HourAriaLabel }})" TValue="int" Disabled="@Disabled" Value="@(HourFormat == "12" ? ((CurrentDate.Hour + 11) % 12) + 1 : CurrentDate.Hour)"
                           Min="@(HourFormat == "12" ? 1 : -1)" Max="@(HourFormat == "12" ? 12 : 24)" Step="@HoursStep"
                           Change="@UpdateHour" class="rz-hour-picker" @oninput=@OnUpdateHourInput Format="@(PadHours ? "00" : "")" Name="@($"{UniqueID}-h")" />
                        }
                        @if (ShowMinutes)
                        {
                        <div class="rz-separator">
                            <span>:</span>
                        </div>
                        <RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", MinutesAriaLabel }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Minute" Step="@MinutesStep" Min="0" Max="59"
                           Change="@UpdateMinutes" class="rz-minute-picker" @oninput=@OnUpdateHourMinutes Format="@(PadMinutes ? "00" : "")" Name="@($"{UniqueID}-m")"/>
                        }
                        @if (ShowSeconds)
                        {
                            <div class="rz-separator">
                                <span>:</span>
                            </div>
                            <RadzenNumeric InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", SecondsAriaLabel }})" TValue="int" Disabled="@Disabled" Value="CurrentDate.Second" Step="@SecondsStep" Min="0" Max="59"
                               Change="@UpdateSeconds" class="rz-second-picker" @oninput=@OnUpdateHourSeconds Format="@(PadSeconds ? "00" : "")" Name="@($"{UniqueID}-s")"/>
                        }
                        @if (HourFormat == "12")
                        {
                            <div class="rz-ampm-picker">
                                <button id="@(GetId() + "ampmup")" type="button" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick="@ToggleAmPm" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
                                    <span class="notranslate rzi rzi-chevron-up"></span>
                                </button>
                                <span>@CurrentDate.ToString("tt")</span>
                                <button id="@(GetId() + "ampmdown")" type="button" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" aria-label="@ToggleAmPmAriaLabel" @onclick="@ToggleAmPm" disabled="@Disabled" aria-disabled="@(Disabled ? "true" : "false")">
                                    <span class="notranslate rzi rzi-chevron-down"></span>
                                </button>
                            </div>
                        }
                        @if (ShowTimeOkButton)
                        {
                            <button aria-label="@OkAriaLabel" type="button" class="rz-button rz-button-md rz-secondary" tabindex="0" @onclick="@(args => OnOkClick(fromOkButton: true))">
                                <span class="rz-button-text">@OkAriaLabel</span>
                            </button>
                        }
                    </div>
                }
        </RadzenPopup>

    </div>
}
