<template>
    <div class="tb-hours-detail">
        <h3>{{ translate('tableHeader') }}</h3>

        <ul class="tb-hours-detail__body">
            <dl class="tb-hours-detail__item" v-for="upcoming in upcomingOpeningTimes">
                <dt class="tb-hours-detail__item-day">
                    {{ translate('day.' + weekdayName(upcoming.weekday)) }}
                </dt>
                <dt class="tb-hours-detail__item-date">
                    {{ upcoming.date }}
                </dt>
                <ul class="tb-hours-detail__item-ranges">
                    <template v-if="upcoming.times && upcoming.timeRanges.length > 0">
                        <dl v-for="timeRange in upcoming.timeRanges" class="tb-hours-detail__item-range">
                            <dd class="tb-hours-detail__item-range-value">
                                {{ timeRange }}
                            </dd>
                            <dd v-if="timeRange.comment" class="tb-hours-detail__item-range-comment">
                                {{ timeRange.comment }}
                            </dd>
                        </dl>
                    </template>

                    <dl class="tb-hours-detail__item-range" v-else>
                        <dd class="tb-hours-detail__item-range-value tb-hours-detail__item-range-value--closed">
                            {{ translate('closed') }}
                        </dd>
                        <dd v-if="upcoming.times && upcoming.times.comment" class="tb-hours-detail__item-range-comment">
                            {{ upcoming.times.comment }}
                        </dd>
                    </dl>
                </ul>
            </dl>
        </ul>
    </div>
</template>
<script>
import formatDate from 'date-fns/format';
import { Time, DayBreak } from '@nimius/toubiz-opening-times-calculation';
import { hasLanguageLabels } from './has-language-label.mixin';

export default {
    name :'TbOpeningTimesTable',
    mixins: [ hasLanguageLabels ],

    props: {
        openingTimes: { type: Object, required: true },
        dateFormat: { type: String, default: 'YYYY-MM-DD' },
        forDateAndTime: { type: Date, default: new Date() },
        length: { type: Number, default: 7 },
    },

    computed: {
        upcomingOpeningTimes() {
            if (!this.openingTimes) {
                return [];
            }

            // More dates than necessary are added in order to have enough data for calculations. They are removed
            // from the array in the end.
            const dates = this.getDatesRelative(-2, this.length + 1);
            const openingTimesForDate = dates.map(date => this.openingTimes.openingTimesForDate(date));
            const timeRangesWithoutSpillOver = openingTimesForDate.map(times => times ? times.timeRanges : []);
            const timeRanges = DayBreak.applyDaySpillingInformationToListOfTimeRanges(timeRangesWithoutSpillOver);

            const upcomingOpeningTimes = [];
            for (let i = 0; i < timeRanges.length; i++) {
                upcomingOpeningTimes.push({
                    weekday: dates[i].getDay(),
                    date: formatDate(dates[i], this.dateFormat),
                    times: openingTimesForDate[i],
                    timeRanges: timeRanges[i],
                });
            }

            // First & Last item were only added to have enough information for the spill-over calculation.
            upcomingOpeningTimes.splice(0, 1);
            upcomingOpeningTimes.pop();

            // First remaining item is one day before desired start date. It is not removed if the desired start date
            // is today and it has opening times spilling over into today.
            const spillOverFromYesterday = upcomingOpeningTimes[0].timeRanges
                .filter(range => range.spillsOverIntoNextDay);
            const spillsOver = spillOverFromYesterday.length > 0
                && Time.now().isBefore(spillOverFromYesterday[0].end);
            if (!(this.checkedDateIsToday && spillsOver)) {
                upcomingOpeningTimes.splice(0, 1);
            }

            return upcomingOpeningTimes;
        },

        checkedDateIsToday() {
            return (new Date).toISOString().substr(0, 10) === this.forDateAndTime.toISOString().substr(0, 10);
        },
    },

    methods: {
        getDatesRelative(startOffset, endOffset) {
            const dates = [];
            for (let i = startOffset; i < endOffset; i++) {
                const date = new Date(this.forDateAndTime);
                date.setDate(date.getDate() + i);
                dates.push(date);
            }
            return dates;
        },
        weekdayName(number) {
            switch (number) {
                case 1: return 'monday';
                case 2: return 'tuesday';
                case 3: return 'wednesday';
                case 4: return 'thursday';
                case 5: return 'friday';
                case 6: return 'saturday';
                case 7:
                case 0:
                    return 'sunday';
            }
        },

    },
};
</script>
