import { MDCRipple } from '@material/ripple';
import { h } from '@stencil/core';
import { capitalizeFirstLetter, isInDateRange } from '../../utils/utils';
export class Datepicker {
    constructor() {
        this.currentMonth = new Date(new Date().setHours(0, 0, 0, 0));
        /** Display year picker on the element */
        this.yearPicker = true;
        /** Display month picker on the element */
        this.monthPicker = true;
        /** Display button for selecting today's date */
        this.todayPicker = true;
        /** Display button to empty value of the element */
        this.nullable = false;
        /**
         * Used to highlight a time period such as : from Monday to Sunday
         */
        this.dateRange = { start: new Date(), end: new Date() };
        /**
         * Used to display current selected date
         */
        this.dateSelected = new Date(new Date().setHours(0, 0, 0, 0));
    }
    componentWillLoad() {
        this.dateSelected = this.isValidDate(this.dateSelected);
        this.dateSelectedClick(this.dateSelected);
    }
    componentDidLoad() {
        Array.from(this.host.shadowRoot.querySelectorAll('.mdc-ripple-surface')).forEach((elem) => {
            MDCRipple.attachTo(elem);
        });
    }
    dateSelectedClick(date, old) {
        if (date) {
            this.currentMonth = new Date(date.setHours(0, 0, 0, 0));
            this.dateSelected = isNaN(Date.parse(date.toString())) ? new Date(new Date().setHours(0, 0, 0, 0)) : date;
            if (isNaN(Date.parse(date.toString())))
                return;
            if (date !== old && date !== this.dateSelected) {
                this.dateSelectedUpdate.emit(this.dateSelected);
            }
        }
    }
    isValidDate(d) {
        const dateParse = Date.parse(d);
        return isNaN(dateParse) ? new Date() : new Date(dateParse);
    }
    addYear(nb) {
        const newDate = new Date(this.currentMonth);
        newDate.setFullYear(newDate.getFullYear() + nb);
        this.currentMonth = newDate;
    }
    addMonth(nb) {
        // setMonth does not trigger update of the State property, we have to reassign
        const newDate = new Date(this.currentMonth);
        newDate.setMonth(newDate.getMonth() + nb);
        this.currentMonth = newDate;
    }
    addDays(date, days) {
        const result = new Date(date);
        result.setDate(result.getDate() + days);
        return result;
    }
    setDateSelected(date) {
        if (date) {
            date.setHours(0, 0, 0, 0);
        }
        this.dateSelected = date;
    }
    startOfWeek(d) {
        d = new Date(d);
        const day = d.getDay();
        const diff = d.getDate() - day + (day === 0 ? -6 : 1); // adjust when day is sunday
        return new Date(d.setDate(diff));
    }
    getDaysOfMonth() {
        const days = [];
        let firstDate = new Date(this.currentMonth.getTime());
        firstDate = new Date(firstDate.getFullYear(), firstDate.getMonth(), 1);
        firstDate = this.startOfWeek(firstDate);
        days.push(firstDate);
        for (let i = 0; i < 41; i++) { // 41 = 6*7 -1 to get 6 weeks
            const day = new Date(new Date(firstDate.getTime()).setHours(0, 0, 0, 0));
            days.push(this.addDays(day, 1 + i));
        }
        const res = [];
        for (let nbWeek = 0; nbWeek < 6; nbWeek++) {
            res.push(days.slice(nbWeek * 7, nbWeek * 7 + 7));
        }
        return res;
    }
    getClasses(day, index) {
        const classes = {
            'day-overview ': true,
            'mdc-ripple-surface': true,
            'mdc-ripple-surface--primary': true,
            'pointer': true,
            'day-current': this.isCurrentDay(day),
            'day-in-month': (this.isInMonth(day.getDate(), index)),
            'day-selected': (this.dateSelected && day.getTime() === this.dateSelected.getTime() && !this.isCurrentDay(day)),
            'in-selected-range': isInDateRange(day, this.dateRange.start, this.dateRange.end) && !this.isSameDate(),
        };
        return classes;
    }
    isInMonth(day, week) {
        if (week === 0 && day > 8) { // first row
            return true;
        }
        if (week >= 4 && day < 15) { // last 2 row
            return true;
        }
        return false;
    }
    isCurrentDay(day) {
        const today = new Date(new Date().setHours(0, 0, 0, 0));
        return day.getTime() === today.getTime();
    }
    isSameDate() {
        return new Date(new Date(this.dateRange.start.setHours(0, 0, 0, 0))).getTime() === new Date(new Date(this.dateRange.end).setHours(0, 0, 0, 0)).getTime();
    }
    render() {
        return (h("div", { class: "month-navigator mdc-typography" },
            this.yearPicker &&
                h("div", { class: "year-picker" },
                    h("materials-icon-button", { dense: true, icon: "chevron_left", title: "Ann\u00E9e pr\u00E9c\u00E9dente", onClick: () => this.addYear(-1) }),
                    capitalizeFirstLetter(this.currentMonth.toLocaleString('fr-fr', { year: 'numeric' })),
                    h("materials-icon-button", { dense: true, icon: "chevron_right", title: "Ann\u00E9e suivant", onClick: () => this.addYear(1) })),
            this.monthPicker &&
                h("div", { class: "month-picker" },
                    h("materials-icon-button", { dense: true, icon: "chevron_left", title: "Mois pr\u00E9c\u00E9dent", onClick: () => this.addMonth(-1) }),
                    capitalizeFirstLetter(this.currentMonth.toLocaleString('fr-fr', { month: 'long', year: this.yearPicker ? undefined : 'numeric' }))
                /**If yearPicker false display year next to month */ ,
                    h("materials-icon-button", { dense: true, icon: "chevron_right", title: "Mois suivant", onClick: () => this.addMonth(1) })),
            h("div", { class: "week-overview" },
                h("span", { class: "day-name", title: "Lundi" }, "L"),
                h("span", { class: "day-name", title: "Mardi" }, "M"),
                h("span", { class: "day-name", title: "Mercredi" }, "M"),
                h("span", { class: "day-name", title: "Jeudi" }, "J"),
                h("span", { class: "day-name", title: "Vendredi" }, "V"),
                h("span", { class: "day-name", title: "Samedi" }, "S"),
                h("span", { class: "day-name", title: "Dimanche" }, "D")),
            this
                .getDaysOfMonth()
                .map((week, index) => h("div", { class: "week-overview" }, week.map(day => {
                return (h("a", { class: this.getClasses(day, index), onClick: () => {
                        this.dateSelectedUpdate.emit(day);
                    } },
                    h("div", { class: { 'day-detail': true }, "data-datepicker": day.toJSON() }, day.getDate())));
            }))),
            h("div", { class: "actions" },
                this.nullable &&
                    h("materials-button", { outlined: true, block: true, dense: true, onClick: () => {
                            this.setDateSelected(null);
                            this.dateSelectedUpdate.emit(null);
                        } }, "Vider"),
                this.todayPicker &&
                    h("materials-button", { block: true, dense: true, onClick: () => {
                            this.setDateSelected(new Date());
                            this.dateSelectedUpdate.emit(this.dateSelected);
                        }, raised: true }, "Aujourd'hui"))));
    }
    static get is() { return "materials-datepicker"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() { return {
        "$": ["datepicker.scss"]
    }; }
    static get styleUrls() { return {
        "$": ["datepicker.css"]
    }; }
    static get properties() { return {
        "yearPicker": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Display year picker on the element"
            },
            "attribute": "year-picker",
            "reflect": false,
            "defaultValue": "true"
        },
        "monthPicker": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Display month picker on the element"
            },
            "attribute": "month-picker",
            "reflect": false,
            "defaultValue": "true"
        },
        "todayPicker": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Display button for selecting today's date"
            },
            "attribute": "today-picker",
            "reflect": false,
            "defaultValue": "true"
        },
        "nullable": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Display button to empty value of the element"
            },
            "attribute": "nullable",
            "reflect": false,
            "defaultValue": "false"
        },
        "dateRange": {
            "type": "unknown",
            "mutable": true,
            "complexType": {
                "original": "{ start: Date, end: Date }",
                "resolved": "{ start: Date; end: Date; }",
                "references": {
                    "Date": {
                        "location": "global"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Used to highlight a time period such as : from Monday to Sunday"
            },
            "defaultValue": "{ start: new Date(), end: new Date() }"
        },
        "dateSelected": {
            "type": "unknown",
            "mutable": true,
            "complexType": {
                "original": "Date",
                "resolved": "Date",
                "references": {
                    "Date": {
                        "location": "global"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Used to display current selected date"
            },
            "defaultValue": "new Date(new Date().setHours(0, 0, 0, 0))"
        }
    }; }
    static get states() { return {
        "currentMonth": {}
    }; }
    static get events() { return [{
            "method": "dateSelectedUpdate",
            "name": "dateSelectedUpdate",
            "bubbles": true,
            "cancelable": true,
            "composed": true,
            "docs": {
                "tags": [],
                "text": "Event emitted when new date is selected"
            },
            "complexType": {
                "original": "Date",
                "resolved": "Date",
                "references": {
                    "Date": {
                        "location": "global"
                    }
                }
            }
        }]; }
    static get elementRef() { return "host"; }
    static get watchers() { return [{
            "propName": "dateSelected",
            "methodName": "dateSelectedClick"
        }]; }
}
