import { KeyboardEvent, FC, PureComponent } from 'react';
import { SupportedWixLocales } from '@wix/design-systems-locale-utils';

export interface dateIndicationProps {
  date: Date;
  isSelected: boolean;
}

export type LanguageType = SupportedWixLocales;

export interface CalendarProps {
  /** Applies as data-hook HTML attribute that can be used in the tests */
  dataHook?: string;
  /** Focus selected day automatically when component mounts or updates
   * @default true
   */
  autoFocus?: boolean;
  /** Allows to display multiple months at once. Currently it shows 1 or 2 months only.
   * @default 1
   */
  numOfMonths?: 1 | 2;
  /** Specifies a CSS class name to be appended to the component’s root element.
   * @internal
   * @default ''
   */
  className?: string;
  /** Provides a callback function when day in selected in the calendar */
  onChange: (date: Date) => void;
  /** Defines a callback function that is called with the date of the first day of the month whenever the user selects a month in the calendar */
  onMonthChange?: (monthStart: Date) => void;
  /** Defines a callback function that is  called whenever a user presses escape, clicks outside of the element or a date is selected and `shouldCloseOnSelect` is set. Receives an event as a first argument. */
  onClose?: () => void;
  /** Specify whether past dates should be selectable or not
   * @default false
   */
  excludePastDates?: boolean;
  /**
   * ##### Specify selectable dates:
   *  * `param` {Date} `date` - a date to check
   *  * `return` {boolean} - true if `date` should be selectable, false otherwise
   */
  filterDate?: (date: Date) => boolean;
  /** Provides a callback function when any key is clicked in the calendar */
  onKeyDown?: (event: KeyboardEvent) => void;
  /** Defines the selected date */
  value?:
    | Date
    | {
        from?: string | Date;
        to?: string | Date;
      };
  /** Whether the user should be able to select a date range, or just a single day
   * @default 'day'
   */
  selectionMode?: 'day' | 'range';
  /** Displays a selectable yearDropdown
   * @default false
   */
  showYearDropdown?: boolean;
  /** Displays a selectable monthDropdown
   * @default false
   */
  showMonthDropdown?: boolean;
  /** Specify whether the calendar closes on day selection
   * @default true
   */
  shouldCloseOnSelect?: boolean;
  /** Specify date picker instance locale */
  locale?: SupportedWixLocales;
  /** First day of the week, allowing only from 0 to 6 (Sunday to Saturday). The default value is 1 which means Monday. */
  firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
  /** Specify whether RTL mode is enabled or not. When true, the keyboard navigation will be changed means pressing on the right arrow will navigate to the previous day, and pressing on the left arrow will navigate to the next day. */
  rtl?: boolean;
  /**
   ##### Add an indication under a specific date.
   Function returns the indication node of a specific date or null if this day doesn't have an indication.
   * - `param` {date: Date, isSelected: boolean }
   * - `date` - a date
   * - `isSelected` - whether this date is the selected date
   * - `return` {React.node} - the indication node of a specific date or null if this day doesn't have an indication.
   */
  dateIndication?: FC<dateIndicationProps>;
  /** Sets today's date. The today indication is added automatically according to the user timezone but in some cases, we need the ability to add the today indication based on the business timezone. */
  today?: Date;
  /** Whether focus should be contained within the calendar */
  containFocus?: boolean;
  /** Defines a string value that labels the left arrow in calendar header */
  leftArrowAriaLabel?: string;
  /** Identifies the element that labels the left arrow in calendar header */
  leftArrowAriaLabelledBy?: string;
  /** Defines a string value that labels the right arrow in calendar header */
  rightArrowAriaLabel?: string;
  /** Identifies the element that labels the right arrow in calendar header */
  rightArrowAriaLabelledBy?: string;
  /** Defines a string value that labels the months dropdown in calendar header */
  monthDropdownAriaLabel?: string;
  /** Identifies the element that labels the months dropdown in calendar header */
  monthDropdownAriaLabelledBy?: string;
  /** Defines a string value that labels the years dropdown in calendar header */
  yearDropdownAriaLabel?: string;
  /** Identifies the element that labels the years dropdown in calendar header */
  yearDropdownAriaLabelledBy?: string;
  /** Defines calendar size property. It can be either small or medium (default)
   * @default 'medium'
   */
  size?: 'small' | 'medium';
}

export default class Calendar extends PureComponent<CalendarProps> {
  static areValuesEqual: (value1?: {}, value2?: {}) => boolean;
  static renderDay: (day: any, modifiers: any) => void;
  static optionalParse: (dateOrString: Date | string) => void;
  static parseValue: (value: any) => any;
  static isSingleDay: (value: any) => Date;
  static isRangeValue: (value: any) => boolean;
  static getUpdatedMonth: (
    nextPropsValue: any,
    /** Allows to display multiple months at once. Currently it shows 1 or 2 months only.
     * @default 1
     */
    numOfMonths: number,
    currentMonthDate: any,
  ) => any;
}
