<template>
    <v-row class="match-height">
        <v-col cols="12">
            <v-card>
                <v-layout>
                    <v-navigation-drawer :permanent="alwaysShowNav" v-model="showNav">
                        <div class="mx-6 my-4">
                            <btn-vertical-group :disabled="loading" :buttons="[
                                { name: $t('Categorical Analysis'), value: allAnalysisTypes.CategoricalAnalysis },
                                { name: $t('Trend Analysis'), value: allAnalysisTypes.TrendAnalysis }
                            ]" v-model="queryAnalysisType" />
                        </div>
                        <v-divider />
                        <div class="mx-6 mt-4">
                            <span class="text-subtitle-2">{{ $t('Chart Type') }}</span>
                            <v-select
                                item-title="displayName"
                                item-value="type"
                                class="mt-2"
                                density="compact"
                                :disabled="loading"
                                :items="allChartTypes"
                                v-model="queryChartType"
                            />
                        </div>
                        <div class="mx-6 mt-4">
                            <span class="text-subtitle-2">{{ $t('Sort Order') }}</span>
                            <v-select
                                item-title="displayName"
                                item-value="type"
                                class="mt-2"
                                density="compact"
                                :disabled="loading"
                                :items="allSortingTypesArray"
                                v-model="querySortingType"
                            />
                        </div>
                        <v-tabs show-arrows class="my-4" direction="vertical"
                                :disabled="loading" v-model="queryChartDataType">
                            <v-tab class="tab-text-truncate" :key="dataType.type" :value="dataType.type"
                                   v-for="dataType in allChartDataTypes" v-show="dataType.availableAnalysisTypes[queryAnalysisType]">
                                <span class="text-truncate">{{ $t(dataType.name) }}</span>
                                <v-tooltip activator="parent" location="right">{{ $t(dataType.name) }}</v-tooltip>
                            </v-tab>
                        </v-tabs>
                    </v-navigation-drawer>
                    <v-main>
                        <v-window class="d-flex flex-grow-1 disable-tab-transition w-100-window-container" v-model="activeTab">
                            <v-window-item value="statisticsPage">
                                <v-card variant="flat" min-height="680">
                                    <template #title>
                                        <div class="title-and-toolbar d-flex align-center">
                                            <v-btn class="mr-3 d-md-none" density="compact" color="default" variant="plain"
                                                   :ripple="false" :icon="true" @click="showNav = !showNav">
                                                <v-icon :icon="icons.menu" size="24" />
                                            </v-btn>
                                            <span>{{ $t('Statistics & Analysis') }}</span>
                                            <v-btn-group class="ml-4" color="default" density="comfortable" variant="outlined" divided>
                                                <v-btn :icon="icons.left"
                                                       :disabled="loading || !canShiftDateRange()"
                                                       @click="shiftDateRange(-1)"/>
                                                <v-menu location="bottom">
                                                    <template #activator="{ props }">
                                                        <v-btn :disabled="loading || queryChartDataType === allChartDataTypes.AccountTotalAssets.type || queryChartDataType === allChartDataTypes.AccountTotalLiabilities.type"
                                                               v-bind="props">{{ dateRangeName() }}</v-btn>
                                                    </template>
                                                    <v-list :selected="[queryDateType]">
                                                        <v-list-item :key="dateRange.type" :value="dateRange.type"
                                                                     :append-icon="(queryDateType === dateRange.type ? icons.check : null)"
                                                                     v-for="dateRange in allDateRangesArray">
                                                            <v-list-item-title
                                                                class="cursor-pointer"
                                                                @click="setDateFilter(dateRange.type)">
                                                                {{ dateRange.displayName }}
                                                                <div class="statistics-custom-datetime-range" v-if="dateRange.type === allDateRanges.Custom.type && showCustomDateRange()">
                                                                    <span>{{ queryStartTime }}</span>
                                                                    <span>&nbsp;-&nbsp;</span>
                                                                    <br/>
                                                                    <span>{{ queryEndTime }}</span>
                                                                </div>
                                                            </v-list-item-title>
                                                        </v-list-item>
                                                    </v-list>
                                                </v-menu>
                                                <v-btn :icon="icons.right"
                                                       :disabled="loading || !canShiftDateRange()"
                                                       @click="shiftDateRange(1)"/>
                                            </v-btn-group>

                                            <v-btn density="compact" color="default" variant="text" size="24"
                                                   class="ml-2" :icon="true" :loading="loading" @click="reload">
                                                <template #loader>
                                                    <v-progress-circular indeterminate size="20"/>
                                                </template>
                                                <v-icon :icon="icons.refresh" size="24" />
                                                <v-tooltip activator="parent">{{ $t('Refresh') }}</v-tooltip>
                                            </v-btn>
                                            <v-spacer/>
                                            <v-btn density="comfortable" color="default" variant="text" class="ml-2"
                                                   :disabled="loading" :icon="true">
                                                <v-icon :icon="icons.more" />
                                                <v-menu activator="parent">
                                                    <v-list>
                                                        <v-list-item :prepend-icon="icons.filter"
                                                                     :title="$t('Filter Accounts')"
                                                                     @click="showFilterAccountDialog = true"></v-list-item>
                                                        <v-list-item :prepend-icon="icons.filter"
                                                                     :title="$t('Filter Transaction Categories')"
                                                                     @click="showFilterCategoryDialog = true"></v-list-item>
                                                        <v-divider class="my-2"/>
                                                        <v-list-item to="/app/settings?tab=statisticsSetting"
                                                                     :prepend-icon="icons.filterSettings"
                                                                     :title="$t('Settings')"></v-list-item>
                                                    </v-list>
                                                </v-menu>
                                            </v-btn>
                                        </div>
                                    </template>

                                    <v-card-text class="statistics-overview-title pt-0" :class="{ 'disabled': loading }"
                                                 v-if="queryAnalysisType === allAnalysisTypes.CategoricalAnalysis && (initing || (categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length))">
                                        <span class="statistics-subtitle">{{ totalAmountName }}</span>
                                        <span class="statistics-overview-amount ml-3"
                                              :class="statisticsTextColor"
                                              v-if="!initing && categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length">
                                            {{ getDisplayAmount(categoricalAnalysisData.totalAmount, defaultCurrency) }}
                                        </span>
                                        <v-skeleton-loader class="skeleton-no-margin ml-3 mb-2"
                                                           width="120px" type="text" :loading="true"
                                                           v-else-if="initing"></v-skeleton-loader>
                                    </v-card-text>

                                    <v-card-text class="statistics-overview-title pt-0"
                                                 v-else-if="!initing && ((queryAnalysisType === allAnalysisTypes.CategoricalAnalysis && (!categoricalAnalysisData || !categoricalAnalysisData.items || !categoricalAnalysisData.items.length))
                                                  || (queryAnalysisType === allAnalysisTypes.TrendAnalysis && (!trendsAnalysisData || !trendsAnalysisData.items || !trendsAnalysisData.items.length)))">
                                        <span class="statistics-subtitle statistics-overview-empty-tip">{{ $t('No transaction data') }}</span>
                                    </v-card-text>

                                    <v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === allAnalysisTypes.CategoricalAnalysis && query.categoricalChartType === allCategoricalChartTypes.Pie">
                                        <pie-chart
                                            :items="[
                                                {id: '1', name: '---', value: 60, color: '7c7c7f'},
                                                {id: '2', name: '---', value: 20, color: 'a5a5aa'},
                                                {id: '3', name: '---', value: 20, color: 'c5c5c9'}
                                            ]"
                                            :skeleton="true"
                                            id-field="id"
                                            name-field="name"
                                            value-field="value"
                                            color-field="color"
                                            v-if="initing"
                                        ></pie-chart>
                                        <pie-chart
                                            :items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
                                            :min-valid-percent="0.0001"
                                            :show-value="showAmountInChart"
                                            :enable-click-item="true"
                                            :default-currency="defaultCurrency"
                                            id-field="id"
                                            name-field="name"
                                            value-field="totalAmount"
                                            percent-field="percent"
                                            hidden-field="hidden"
                                            v-else-if="!initing"
                                            @click="clickPieChartItem"
                                        />
                                    </v-card-text>

                                    <v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === allAnalysisTypes.CategoricalAnalysis && query.categoricalChartType === allCategoricalChartTypes.Bar">
                                        <v-list rounded lines="two" v-if="initing">
                                            <template :key="itemIdx" v-for="itemIdx in [ 1, 2, 3 ]">
                                                <v-list-item class="pl-0">
                                                    <template #prepend>
                                                        <div>
                                                            <v-icon class="disabled mr-0" size="34" :icon="icons.square" />
                                                        </div>
                                                    </template>
                                                    <div class="d-flex flex-column ml-2">
                                                        <div class="d-flex">
                                                            <v-skeleton-loader class="skeleton-no-margin my-2"
                                                                               width="120px" type="text" :loading="true"></v-skeleton-loader>
                                                        </div>
                                                        <div>
                                                            <v-progress-linear :model-value="0" :height="4"></v-progress-linear>
                                                        </div>
                                                    </div>
                                                </v-list-item>
                                                <v-divider v-if="itemIdx < 3"/>
                                            </template>
                                        </v-list>
                                        <v-list class="py-0" rounded lines="two" v-else-if="!initing && categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length">
                                            <template :key="idx"
                                                      v-for="(item, idx) in categoricalAnalysisData.items">
                                                <v-list-item class="pl-0" v-if="!item.hidden">
                                                    <template #prepend>
                                                        <router-link class="statistics-list-item" :to="getTransactionItemLinkUrl(item)">
                                                            <ItemIcon :icon-type="queryChartDataCategory" size="34px"
                                                                      :icon-id="item.icon"
                                                                      :color="item.color"></ItemIcon>
                                                        </router-link>
                                                    </template>
                                                    <router-link class="statistics-list-item" :to="getTransactionItemLinkUrl(item)">
                                                        <div class="d-flex flex-column ml-2">
                                                            <div class="d-flex">
                                                                <span>{{ item.name }}</span>
                                                                <small class="statistics-percent" v-if="item.percent >= 0">{{ getDisplayPercent(item.percent, 2, '&lt;0.01') }}</small>
                                                                <v-spacer/>
                                                                <span class="statistics-amount">{{ getDisplayAmount(item.totalAmount, (item.currency || defaultCurrency)) }}</span>
                                                            </div>
                                                            <div>
                                                                <v-progress-linear :color="item.color ? '#' + item.color : 'primary'"
                                                                                   :bg-color="isDarkMode ? '#161616' : '#f8f8f8'" :bg-opacity="1"
                                                                                   :model-value="item.percent >= 0 ? item.percent : 0"
                                                                                   :height="4"></v-progress-linear>
                                                            </div>
                                                        </div>
                                                    </router-link>
                                                </v-list-item>
                                                <v-divider v-if="!item.hidden && idx !== categoricalAnalysisData.items.length - 1"/>
                                            </template>
                                        </v-list>
                                    </v-card-text>

                                    <v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === allAnalysisTypes.TrendAnalysis">
                                        <trends-chart
                                            :type="queryChartType"
                                            :start-year-month="query.trendChartStartYearMonth"
                                            :end-year-month="query.trendChartEndYearMonth"
                                            :items="[]"
                                            :skeleton="true"
                                            id-field="id"
                                            name-field="name"
                                            value-field="value"
                                            color-field="color"
                                            v-if="initing"
                                        ></trends-chart>
                                        <trends-chart
                                            :type="queryChartType"
                                            :start-year-month="query.trendChartStartYearMonth"
                                            :end-year-month="query.trendChartEndYearMonth"
                                            :sorting-type="querySortingType"
                                            :items="trendsAnalysisData && trendsAnalysisData.items && trendsAnalysisData.items.length ? trendsAnalysisData.items : []"
                                            :translate-name="translateNameInTrendsChart"
                                            :show-value="showAmountInChart"
                                            :enable-click-item="true"
                                            :default-currency="defaultCurrency"
                                            :show-total-amount-in-tooltip="showTotalAmountInTrendsChart"
                                            id-field="id"
                                            name-field="name"
                                            value-field="totalAmount"
                                            hidden-field="hidden"
                                            display-orders-field="displayOrders"
                                            v-else-if="!initing && trendsAnalysisData && trendsAnalysisData.items && trendsAnalysisData.items.length"
                                            @click="clickTrendChartItem"
                                        />
                                    </v-card-text>
                                </v-card>
                            </v-window-item>
                        </v-window>
                    </v-main>
                </v-layout>
            </v-card>
        </v-col>
    </v-row>

    <date-range-selection-dialog :title="$t('Custom Date Range')"
                                  :min-time="query.categoricalChartStartTime"
                                  :max-time="query.categoricalChartEndTime"
                                  v-model:show="showCustomDateRangeDialog"
                                  @dateRange:change="setCustomDateFilter" />

    <month-range-selection-dialog :title="$t('Custom Date Range')"
                                  :min-time="query.trendChartStartYearMonth"
                                  :max-time="query.trendChartEndYearMonth"
                                  v-model:show="showCustomMonthRangeDialog"
                                  @dateRange:change="setCustomDateFilter" />

    <v-dialog width="800" v-model="showFilterAccountDialog">
        <account-filter-settings-card type="statisticsCurrent" :dialog-mode="true"
            @settings:change="setAccountFilter" />
    </v-dialog>

    <v-dialog width="800" v-model="showFilterCategoryDialog">
        <category-filter-settings-card type="statisticsCurrent" :dialog-mode="true"
            @settings:change="setCategoryFilter" />
    </v-dialog>

    <snack-bar ref="snackbar" />
</template>

<script>
import { useDisplay, useTheme } from 'vuetify';

import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import { useAccountsStore } from '@/stores/account.js';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
import { useStatisticsStore } from '@/stores/statistics.js';

import datetimeConstants from '@/consts/datetime.js';
import statisticsConstants from '@/consts/statistics.js';
import {
    isDefined,
    limitText,
    arrayItemToObjectField
} from '@/lib/common.js'
import { formatPercent } from '@/lib/numeral.js';
import {
    getYearAndMonthFromUnixTime,
    getYearMonthFirstUnixTime,
    getYearMonthLastUnixTime,
    getShiftedDateRangeAndDateType,
    getDateTypeByDateRange,
    getDateRangeByDateType
} from '@/lib/datetime.js';
import { isChartDataTypeAvailableForAnalysisType } from '@/lib/statistics.js';

import {
    mdiCheck,
    mdiArrowLeft,
    mdiArrowRight,
    mdiSort,
    mdiRefresh,
    mdiSquareRounded,
    mdiMenu,
    mdiFilterOutline,
    mdiFilterCogOutline,
    mdiPencilOutline,
    mdiDotsVertical
} from '@mdi/js';

import AccountFilterSettingsCard from '@/views/desktop/common/cards/AccountFilterSettingsCard.vue';
import CategoryFilterSettingsCard from '@/views/desktop/common/cards/CategoryFilterSettingsCard.vue';

export default {
    components: {
        AccountFilterSettingsCard,
        CategoryFilterSettingsCard
    },
    props: [
        'initAnalysisType',
        'initChartDataType',
        'initChartType',
        'initChartDateType',
        'initStartTime',
        'initEndTime',
        'initFilterAccountIds',
        'initFilterCategoryIds',
        'initSortingType'
    ],
    data() {
        const { mdAndUp } = useDisplay();

        return {
            activeTab: 'statisticsPage',
            initing: true,
            loading: true,
            alwaysShowNav: mdAndUp.value,
            showNav: mdAndUp.value,
            analysisType: statisticsConstants.allAnalysisTypes.CategoricalAnalysis,
            showCustomDateRangeDialog: false,
            showCustomMonthRangeDialog: false,
            showFilterAccountDialog: false,
            showFilterCategoryDialog: false,
            icons: {
                check: mdiCheck,
                left: mdiArrowLeft,
                right: mdiArrowRight,
                sort: mdiSort,
                refresh: mdiRefresh,
                square: mdiSquareRounded,
                menu: mdiMenu,
                filter: mdiFilterOutline,
                filterSettings: mdiFilterCogOutline,
                pencil: mdiPencilOutline,
                more: mdiDotsVertical
            }
        };
    },
    computed: {
        ...mapStores(useSettingsStore, useUserStore, useAccountsStore, useTransactionCategoriesStore, useStatisticsStore),
        isDarkMode() {
            return this.globalTheme.global.name.value === 'dark';
        },
        defaultCurrency() {
            return this.userStore.currentUserDefaultCurrency;
        },
        firstDayOfWeek() {
            return this.userStore.currentUserFirstDayOfWeek;
        },
        queryAnalysisType: {
            get: function () {
                return this.analysisType;
            },
            set: function(value) {
                this.setAnalysisType(value);
            }
        },
        query() {
            return this.statisticsStore.transactionStatisticsFilter;
        },
        queryChartDataCategory() {
            return this.statisticsStore.categoricalAnalysisChartDataCategory;
        },
        queryChartType: {
            get: function () {
                if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                    return this.query.categoricalChartType;
                } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                    return this.query.trendChartType;
                } else {
                    return null;
                }
            },
            set: function(value) {
                this.setChartType(value);
            }
        },
        queryChartDataType: {
            get: function () {
                return this.query.chartDataType;
            },
            set: function(value) {
                this.setChartDataType(value);
            }
        },
        querySortingType: {
            get: function () {
                return this.query.sortingType;
            },
            set: function(value) {
                this.setSortingType(value);
            }
        },
        queryDateType() {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.query.categoricalChartDateType;
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.query.trendChartDateType;
            } else {
                return null;
            }
        },
        queryStartTime() {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.query.categoricalChartStartTime);
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.$locale.formatUnixTimeToLongYearMonth(this.userStore, getYearMonthFirstUnixTime(this.query.trendChartStartYearMonth));
            } else {
                return '';
            }
        },
        queryEndTime() {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.$locale.formatUnixTimeToLongDateTime(this.userStore, this.query.categoricalChartEndTime);
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.$locale.formatUnixTimeToLongYearMonth(this.userStore, getYearMonthLastUnixTime(this.query.trendChartEndYearMonth));
            } else {
                return '';
            }
        },
        allAnalysisTypes() {
            return statisticsConstants.allAnalysisTypes;
        },
        allChartTypes() {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.$locale.getAllCategoricalChartTypes();
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.$locale.getAllTrendChartTypes();
            } else {
                return [];
            }
        },
        allCategoricalChartTypes() {
            return statisticsConstants.allCategoricalChartTypes;
        },
        allChartDataTypes() {
            return statisticsConstants.allChartDataTypes;
        },
        allSortingTypes() {
            return statisticsConstants.allSortingTypes;
        },
        allSortingTypesArray() {
            return this.$locale.getAllStatisticsSortingTypes();
        },
        allDateRanges() {
            return datetimeConstants.allDateRanges;
        },
        allDateRangesArray() {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.$locale.getAllDateRanges(datetimeConstants.allDateRangeScenes.Normal, true);
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.$locale.getAllDateRanges(datetimeConstants.allDateRangeScenes.TrendAnalysis, true);
            } else {
                return [];
            }
        },
        showAccountBalance() {
            return this.settingsStore.appSettings.showAccountBalance;
        },
        totalAmountName() {
            if (this.queryChartDataType === this.allChartDataTypes.IncomeByAccount.type
                || this.queryChartDataType === this.allChartDataTypes.IncomeByPrimaryCategory.type
                || this.queryChartDataType === this.allChartDataTypes.IncomeBySecondaryCategory.type) {
                return this.$t('Total Income');
            } else if (this.queryChartDataType === this.allChartDataTypes.ExpenseByAccount.type
                || this.queryChartDataType === this.allChartDataTypes.ExpenseByPrimaryCategory.type
                || this.queryChartDataType === this.allChartDataTypes.ExpenseBySecondaryCategory.type) {
                return this.$t('Total Expense');
            } else if (this.queryChartDataType === this.allChartDataTypes.AccountTotalAssets.type) {
                return this.$t('Total Assets');
            } else if (this.queryChartDataType === this.allChartDataTypes.AccountTotalLiabilities.type) {
                return this.$t('Total Liabilities');
            }

            return this.$t('Total Amount');
        },
        categoricalAnalysisData() {
            return this.statisticsStore.categoricalAnalysisData;
        },
        trendsAnalysisData() {
            return this.statisticsStore.trendsAnalysisData;
        },
        translateNameInTrendsChart() {
            return this.queryChartDataType === this.allChartDataTypes.TotalExpense.type ||
                this.queryChartDataType === this.allChartDataTypes.TotalIncome.type ||
                this.queryChartDataType === this.allChartDataTypes.TotalBalance.type;
        },
        showTotalAmountInTrendsChart() {
            return this.queryChartDataType !== this.allChartDataTypes.TotalExpense.type &&
                this.queryChartDataType !== this.allChartDataTypes.TotalIncome.type &&
                this.queryChartDataType !== this.allChartDataTypes.TotalBalance.type;
        },
        statisticsTextColor() {
            if (this.queryChartDataType === this.allChartDataTypes.ExpenseByAccount.type ||
                this.queryChartDataType === this.allChartDataTypes.ExpenseByPrimaryCategory.type ||
                this.queryChartDataType === this.allChartDataTypes.ExpenseBySecondaryCategory.type) {
                return 'text-expense';
            } else if (this.queryChartDataType === this.allChartDataTypes.IncomeByAccount.type ||
                this.queryChartDataType === this.allChartDataTypes.IncomeByPrimaryCategory.type ||
                this.queryChartDataType === this.allChartDataTypes.IncomeBySecondaryCategory.type) {
                return 'text-income';
            } else {
                return 'text-default';
            }
        },
        showAmountInChart() {
            if (!this.showAccountBalance
                && (this.queryChartDataType === this.allChartDataTypes.AccountTotalAssets.type || this.queryChartDataType === this.allChartDataTypes.AccountTotalLiabilities.type)) {
                return false;
            }

            return true;
        }
    },
    watch: {
        'display.mdAndUp.value': function (newValue) {
            this.alwaysShowNav = newValue;

            if (!this.showNav) {
                this.showNav = newValue;
            }
        }
    },
    created() {
        this.init({
            analysisType: this.initAnalysisType,
            chartDataType: this.initChartDataType,
            chartType: this.initChartType,
            chartDateType: this.initChartDateType,
            startTime: this.initStartTime,
            endTime: this.initEndTime,
            filterAccountIds: this.initFilterAccountIds,
            filterCategoryIds: this.initFilterCategoryIds,
            sortingType: this.initSortingType,
        });
    },
    setup() {
        const display = useDisplay();
        const theme = useTheme();

        return {
            display: display,
            globalTheme: theme
        };
    },
    beforeRouteUpdate(to) {
        if (to.query) {
            this.init({
                analysisType: to.query.analysisType,
                chartDataType: to.query.chartDataType,
                chartType: to.query.chartType,
                chartDateType: to.query.chartDateType,
                startTime: to.query.startTime,
                endTime: to.query.endTime,
                filterAccountIds: to.query.filterAccountIds,
                filterCategoryIds: to.query.filterCategoryIds,
                sortingType: to.query.sortingType
            });
        } else {
            this.init({});
        }
    },
    methods: {
        init(query) {
            const self = this;
            let needReload = !isDefined(query.analysisType);

            let filter = {
                chartDataType: query.chartDataType ? parseInt(query.chartDataType) : undefined,
                filterAccountIds: query.filterAccountIds ? arrayItemToObjectField(query.filterAccountIds.split(','), true) : {},
                filterCategoryIds: query.filterCategoryIds ? arrayItemToObjectField(query.filterCategoryIds.split(','), true) : {},
                sortingType: query.sortingType ? parseInt(query.sortingType) : undefined
            };

            if (query.analysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis.toString()) {
                filter.categoricalChartType = query.chartType ? parseInt(query.chartType) : undefined;
                filter.categoricalChartDateType = query.chartDateType ? parseInt(query.chartDateType) : undefined;
                filter.categoricalChartStartTime = query.startTime ? parseInt(query.startTime) : undefined;
                filter.categoricalChartEndTime = query.endTime ? parseInt(query.endTime) : undefined;

                if (filter.categoricalChartDateType !== self.query.categoricalChartDateType) {
                    needReload = true;
                } else if (filter.categoricalChartDateType === datetimeConstants.allDateRanges.Custom.type) {
                    if (filter.categoricalChartStartTime !== self.query.categoricalChartStartTime
                        || filter.categoricalChartEndTime !== self.query.categoricalChartEndTime) {
                        needReload = true;
                    }
                }

                if (query.analysisType !== self.queryAnalysisType.toString()) {
                    self.analysisType = statisticsConstants.allAnalysisTypes.CategoricalAnalysis;
                    needReload = true;
                }
            } else if (query.analysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis.toString()) {
                filter.trendChartType = query.chartType ? parseInt(query.chartType) : undefined;
                filter.trendChartDateType = query.chartDateType ? parseInt(query.chartDateType) : undefined;
                filter.trendChartStartYearMonth = query.startTime;
                filter.trendChartEndYearMonth = query.endTime;

                if (filter.trendChartDateType !== self.query.trendChartDateType) {
                    needReload = true;
                } else if (filter.trendChartDateType === datetimeConstants.allDateRanges.Custom.type) {
                    if (filter.trendChartStartYearMonth !== self.query.trendChartStartYearMonth
                        || filter.trendChartEndYearMonth !== self.query.trendChartEndYearMonth) {
                        needReload = true;
                    }
                }

                if (query.analysisType !== self.queryAnalysisType.toString()) {
                    self.analysisType = statisticsConstants.allAnalysisTypes.TrendAnalysis;
                    needReload = true;
                }
            }

            if (!isDefined(query.analysisType)) {
                self.analysisType = statisticsConstants.allAnalysisTypes.CategoricalAnalysis;
                filter = null;
            }

            self.statisticsStore.initTransactionStatisticsFilter(self.queryAnalysisType, filter);

            if (!needReload && !self.statisticsStore.transactionStatisticsStateInvalid) {
                self.loading = false;
                self.initing = false;
                return;
            }

            Promise.all([
                self.accountsStore.loadAllAccounts({force: false}),
                self.transactionCategoriesStore.loadAllCategories({force: false})
            ]).then(() => {
                if (self.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                    return self.statisticsStore.loadCategoricalAnalysis({
                        force: false
                    });
                } else if (self.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                    return self.statisticsStore.loadTrendAnalysis({
                        force: false
                    });
                }
            }).then(() => {
                self.loading = false;
                self.initing = false;
            }).catch(error => {
                self.loading = false;
                self.initing = false;

                if (!error.processed) {
                    self.$refs.snackbar.showError(error);
                }
            });
        },
        reload(force) {
            const self = this;
            let dispatchPromise = null;

            self.loading = true;

            if (self.queryChartDataType === self.allChartDataTypes.ExpenseByAccount.type ||
                self.queryChartDataType === self.allChartDataTypes.ExpenseByPrimaryCategory.type ||
                self.queryChartDataType === self.allChartDataTypes.ExpenseBySecondaryCategory.type ||
                self.queryChartDataType === self.allChartDataTypes.IncomeByAccount.type ||
                self.queryChartDataType === self.allChartDataTypes.IncomeByPrimaryCategory.type ||
                self.queryChartDataType === self.allChartDataTypes.IncomeBySecondaryCategory.type ||
                self.queryChartDataType === self.allChartDataTypes.TotalExpense.type ||
                self.queryChartDataType === self.allChartDataTypes.TotalIncome.type ||
                self.queryChartDataType === self.allChartDataTypes.TotalBalance.type) {
                if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                    dispatchPromise = self.statisticsStore.loadCategoricalAnalysis({
                        force: force
                    });
                } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                    dispatchPromise = self.statisticsStore.loadTrendAnalysis({
                        force: force
                    });
                }
            } else if (self.queryChartDataType === self.allChartDataTypes.AccountTotalAssets.type ||
                self.queryChartDataType === self.allChartDataTypes.AccountTotalLiabilities.type) {
                dispatchPromise = self.accountsStore.loadAllAccounts({
                    force: force
                });
            }

            if (dispatchPromise) {
                dispatchPromise.then(() => {
                    self.loading = false;

                    if (force) {
                        self.$refs.snackbar.showMessage('Data has been updated');
                    }
                }).catch(error => {
                    self.loading = false;

                    if (!error.processed) {
                        self.$refs.snackbar.showError(error);
                    }
                });
            }

            return dispatchPromise;
        },
        setAnalysisType(analysisType) {
            if (this.analysisType === analysisType) {
                return;
            }

            if (!isChartDataTypeAvailableForAnalysisType(this.queryChartDataType, analysisType)) {
                this.statisticsStore.updateTransactionStatisticsFilter({
                    chartDataType: statisticsConstants.defaultChartDataType
                });
            }

            this.analysisType = analysisType;
            this.loading = true;
            this.statisticsStore.updateTransactionStatisticsInvalidState(true);
            this.$router.push(this.getFilterLinkUrl());
        },
        setChartType(chartType) {
            let changed = false;

            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    categoricalChartType: chartType
                });
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    trendChartType: chartType
                });
            }

            if (changed) {
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        setChartDataType(chartDataType) {
            const changed = this.statisticsStore.updateTransactionStatisticsFilter({
                chartDataType: chartDataType
            });

            if (changed) {
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        setSortingType(sortingType) {
            if (sortingType < this.allSortingTypes.Amount.type || sortingType > this.allSortingTypes.Name.type) {
                return;
            }

            const changed = this.statisticsStore.updateTransactionStatisticsFilter({
                sortingType: sortingType
            });

            if (changed) {
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        setDateFilter(dateType) {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                if (dateType === this.allDateRanges.Custom.type) { // Custom
                    this.showCustomDateRangeDialog = true;
                    return;
                } else if (this.query.categoricalChartDateType === dateType) {
                    return;
                }
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                if (dateType === this.allDateRanges.Custom.type) { // Custom
                    this.showCustomMonthRangeDialog = true;
                    return;
                } else if (this.query.trendChartDateType === dateType) {
                    return;
                }
            }

            const dateRange = getDateRangeByDateType(dateType, this.firstDayOfWeek);

            if (!dateRange) {
                return;
            }

            let changed = false;

            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    categoricalChartDateType: dateRange.dateType,
                    categoricalChartStartTime: dateRange.minTime,
                    categoricalChartEndTime: dateRange.maxTime
                });
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    trendChartDateType: dateRange.dateType,
                    trendChartStartYearMonth: getYearAndMonthFromUnixTime(dateRange.minTime),
                    trendChartEndYearMonth: getYearAndMonthFromUnixTime(dateRange.maxTime)
                });
            }

            if (changed) {
                this.loading = true;
                this.statisticsStore.updateTransactionStatisticsInvalidState(true);
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        setCustomDateFilter(startTime, endTime) {
            if (!startTime || !endTime) {
                return;
            }

            let changed = false;

            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                const chartDateType = getDateTypeByDateRange(startTime, endTime, this.firstDayOfWeek, datetimeConstants.allDateRangeScenes.Normal);

                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    categoricalChartDateType: chartDateType,
                    categoricalChartStartTime: startTime,
                    categoricalChartEndTime: endTime
                });

                this.showCustomDateRangeDialog = false;
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                const chartDateType = getDateTypeByDateRange(getYearMonthFirstUnixTime(startTime), getYearMonthLastUnixTime(endTime), this.firstDayOfWeek, datetimeConstants.allDateRangeScenes.TrendAnalysis);

                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    trendChartDateType: chartDateType,
                    trendChartStartYearMonth: startTime,
                    trendChartEndYearMonth: endTime
                });

                this.showCustomMonthRangeDialog = false;
            }

            if (changed) {
                this.loading = true;
                this.statisticsStore.updateTransactionStatisticsInvalidState(true);
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        showCustomDateRange() {
            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.query.categoricalChartDateType === this.allDateRanges.Custom.type && this.query.categoricalChartStartTime && this.query.categoricalChartEndTime;
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.query.trendChartDateType === this.allDateRanges.Custom.type && this.query.trendChartStartYearMonth && this.query.trendChartEndYearMonth;
            } else {
                return false;
            }
        },
        canShiftDateRange() {
            if (this.queryChartDataType === this.allChartDataTypes.AccountTotalAssets.type || this.queryChartDataType === this.allChartDataTypes.AccountTotalLiabilities.type) {
                return false;
            }

            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.query.categoricalChartDateType !== this.allDateRanges.All.type;
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.query.trendChartDateType !== this.allDateRanges.All.type;
            } else {
                return false;
            }
        },
        shiftDateRange(scale) {
            if (this.query.categoricalChartDateType === this.allDateRanges.All.type) {
                return;
            }

            let changed = false;

            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                const newDateRange = getShiftedDateRangeAndDateType(this.query.categoricalChartStartTime, this.query.categoricalChartEndTime, scale, this.firstDayOfWeek, datetimeConstants.allDateRangeScenes.Normal);

                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    categoricalChartDateType: newDateRange.dateType,
                    categoricalChartStartTime: newDateRange.minTime,
                    categoricalChartEndTime: newDateRange.maxTime
                });
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                const newDateRange = getShiftedDateRangeAndDateType(getYearMonthFirstUnixTime(this.query.trendChartStartYearMonth), getYearMonthLastUnixTime(this.query.trendChartEndYearMonth), scale, this.firstDayOfWeek, datetimeConstants.allDateRangeScenes.TrendAnalysis);

                changed = this.statisticsStore.updateTransactionStatisticsFilter({
                    trendChartDateType: newDateRange.dateType,
                    trendChartStartYearMonth: getYearAndMonthFromUnixTime(newDateRange.minTime),
                    trendChartEndYearMonth: getYearAndMonthFromUnixTime(newDateRange.maxTime)
                });
            }

            if (changed) {
                this.loading = true;
                this.statisticsStore.updateTransactionStatisticsInvalidState(true);
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        dateRangeName() {
            if (this.queryChartDataType === this.allChartDataTypes.AccountTotalAssets.type ||
                this.queryChartDataType === this.allChartDataTypes.AccountTotalLiabilities.type) {
                return this.$t(this.allDateRanges.All.name);
            }

            if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.CategoricalAnalysis) {
                return this.$locale.getDateRangeDisplayName(this.userStore, this.query.categoricalChartDateType, this.query.categoricalChartStartTime, this.query.categoricalChartEndTime);
            } else if (this.queryAnalysisType === statisticsConstants.allAnalysisTypes.TrendAnalysis) {
                return this.$locale.getDateRangeDisplayName(this.userStore, this.query.trendChartDateType, getYearMonthFirstUnixTime(this.query.trendChartStartYearMonth), getYearMonthLastUnixTime(this.query.trendChartEndYearMonth));
            } else {
                return '';
            }
        },
        setAccountFilter(changed) {
            this.showFilterAccountDialog = false;

            if (changed) {
                this.loading = true;
                this.statisticsStore.updateTransactionStatisticsInvalidState(true);
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        setCategoryFilter(changed) {
            this.showFilterCategoryDialog = false;

            if (changed) {
                this.loading = true;
                this.statisticsStore.updateTransactionStatisticsInvalidState(true);
                this.$router.push(this.getFilterLinkUrl());
            }
        },
        clickPieChartItem(item) {
            this.$router.push(this.getTransactionItemLinkUrl(item));
        },
        clickTrendChartItem(item) {
            const minUnixTime = getYearMonthFirstUnixTime(item.yearMonth);
            const maxUnixTime = getYearMonthLastUnixTime(item.yearMonth);
            const dateRangeType = getDateTypeByDateRange(minUnixTime, maxUnixTime, this.firstDayOfWeek, datetimeConstants.allDateRangeScenes.Normal);

            this.$router.push(this.getTransactionItemLinkUrl(item.item, {
                minTime: minUnixTime,
                maxTime: maxUnixTime,
                type: dateRangeType,
            }));
        },
        getDisplayAmount(amount, currency, textLimit) {
            amount = this.getDisplayCurrency(amount, currency);

            if (!this.showAccountBalance
                && (this.queryChartDataType === this.allChartDataTypes.AccountTotalAssets.type
                    || this.queryChartDataType === this.allChartDataTypes.AccountTotalLiabilities.type)
            ) {
                return '***';
            }

            if (textLimit) {
                return limitText(amount, textLimit);
            }

            return amount;
        },
        getDisplayCurrency(value, currencyCode) {
            return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
        },
        getDisplayPercent(value, precision, lowPrecisionValue) {
            return formatPercent(value, precision, lowPrecisionValue);
        },
        getFilterLinkUrl() {
            return `/statistics/transaction?${this.statisticsStore.getTransactionStatisticsPageParams(this.queryAnalysisType)}`;
        },
        getTransactionItemLinkUrl(item, dateRange) {
            return `/transaction/list?${this.statisticsStore.getTransactionListPageParams(this.queryAnalysisType, item, dateRange)}`;
        }
    }
}
</script>

<style>
.statistics-custom-datetime-range {
    font-size: 0.7rem;
    line-height: 1rem;
    color: rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity)) !important;
}

.statistics-overview-title {
    line-height: 2rem !important;
    height: 46px;
    display: flex;
    align-items: flex-end;
}

.statistics-overview-amount {
    font-size: 1.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.statistics-subtitle {
    font-size: 1rem;
    line-height: 1.75rem
}

.statistics-overview-empty-tip {
    color: rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity)) !important;
}

.statistics-list-item {
    color: var(--v-theme-on-default);
    font-size: 1rem !important;
    line-height: 1.75rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.statistics-list-item .statistics-percent {
    font-size: 0.75rem;
    opacity: 0.7;
    margin-left: 6px;
}

.statistics-list-item .statistics-amount {
    opacity: 0.8;
}
</style>
