export default {
    props: {
        serverData: {
            type: Object,
            required: true
        },
        whmcsPid: {
            type: [
                String,
                Number
            ],
            required: true
        },
        xhrUrl: {
            type: String,
            required: true
        },
        networkGraphShowSummaryByDefault: {
            type: String,
            required: false
        },
        networkGraphShowp95thLineByDefault: {
            type: String,
            required: false
        }
    },

    data() {
        return {
            networkGraphs: [],
            visibleNetworkGraphPort: 0,
            selectedNetworkGraphTimerange: '24h',
            networkStatsShowDetails: false,
            graphZoomStatus: {
                network: false
            },
            isResettingZoom: {
                network: false
            },
            _recalcTimeoutId: null,
            customDateRange: {
                dropdownVisible: false,
                dates: {
                    start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().substr(0, 10),
                    end: new Date().toISOString().substr(0, 10)
                },
                times: {
                    start: '00:00',
                    end: '23:59'
                },
                isActive: false
            },
            graphTabSelection: 'network',
            resourceGraphs: {
                cpu: [],
                memory: [],
                diskio: []
            },
            resourceTimeframes: {
                cpu: '24h',
                memory: '24h',
                diskio: '24h'
            },
            resourceCustomDateRanges: {
                cpu: {
                    dropdownVisible: false,
                    dates: {
                        start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().substr(0, 10),
                        end: new Date().toISOString().substr(0, 10)
                    },
                    times: {
                        start: '00:00',
                        end: '23:59'
                    },
                    isActive: false
                },
                memory: {
                    dropdownVisible: false,
                    dates: {
                        start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().substr(0, 10),
                        end: new Date().toISOString().substr(0, 10)
                    },
                    times: {
                        start: '00:00',
                        end: '23:59'
                    },
                    isActive: false
                },
                diskio: {
                    dropdownVisible: false,
                    dates: {
                        start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().substr(0, 10),
                        end: new Date().toISOString().substr(0, 10)
                    },
                    times: {
                        start: '00:00',
                        end: '23:59'
                    },
                    isActive: false
                }
            },
            statsAvailability: {
                network: null,
                cpu: null,
                memory: null,
                diskio: null
            },
        }
    },

    template: `
        <template v-if="shouldShowGraphsCard">
            <div class="panel panel-default card">
                <div class="panel-body card-body">
                    <div class="btn-group" role="group" style="margin-bottom: 15px;" v-if="shouldShowNetworkTab || shouldShowResourcesTab">
                        <button class="btn" :class="graphTabSelection === 'network' ? 'btn-primary' : 'btn-default'" v-if="shouldShowNetworkTab" @click.prevent="graphTabSelection = 'network'">
                            {{ jsToLang('card.graphs.tab.network') || 'Network Graphs' }}
                        </button>

                        <button class="btn" :class="graphTabSelection === 'resources' ? 'btn-primary' : 'btn-default'" v-if="shouldShowResourcesTab" @click.prevent="switchToResourcesTab()">
                            {{ jsToLang('card.graphs.tab.resources') || 'Resources Graphs' }}
                        </button>
                    </div>


                    <div :style="$simpleStore.getLoader('generateBandwidthCharts') && networkGraphs.length ? 'opacity: 0.5' : 'opacity: 1.0'" v-if="graphTabSelection === 'network'">
                        <template v-if="networkGraphs.length === 0">
                            <div class="text-center">
                                <i style="font-size: 24px;" :class="faIconRepo('fa-refresh-spin')"></i>
                            </div>
                        </template>

                        <template v-else>
                            <div style="margin-bottom: 10px;">
                                <select class="form-control" v-model="visibleNetworkGraphPort" style="width: auto; display: inline-block;" :class="getBsVersion !== 3 ? 'custom-select-sm' : ''">
                                    <option v-for="(v, k) in networkGraphs" :key="'netGraphOption' + k" :value="k">
                                        {{ jsToLang('card.graphs.button.network_port.prefix') }} {{ v.portName }}
                                    </option>
                                </select>

                                <div class="btn-group pull-right float-md-right" role="group" aria-label="Select timerange" v-if="dCan('servers.stats.network.param.predefined')">
                                    <d-button style="pointer-events: auto !important;" v-for="(v, k) in networkGraphs[visibleNetworkGraphPort]?.features?.availablePredefinedValues" :key="'netGraphRangeSelector_' + k"
                                              :disabled="$simpleStore.getLoader('generateBandwidthCharts') || v.available === 0" @click.native="generateBandwidthCharts(v.submitValue)" type="button" class="btn"
                                              :class="[selectedNetworkGraphTimerange === v.submitValue ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']">
                                        <span data-toggle="dynamic-tooltip" :title="v.available === 0 ? jsToLang('card.graphs.button.timerange.not_available_because_of_owner_date') : ''">
                                            {{ v.lang }}
                                        </span>
                                    </d-button>

                                    <div class="btn-group" style="display: inline-block;" v-if="networkGraphs[visibleNetworkGraphPort]?.features?.customRangeAvailable === 1">
                                        <button type="button" class="btn dropdown-toggle" :class="[customDateRange.isActive ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']" data-toggle="dropdown" aria-haspopup="true"
                                                aria-expanded="false" :disabled="$simpleStore.getLoader('generateBandwidthCharts') === 1">
                                            <i :class="faIconRepo('fa-calendar-alt')" style="margin-right: 3px;"></i>
                                            {{ jsToLang('card.graphs.button.timerange.custom') || 'Custom' }}
                                            <span class="caret" style="margin-left: 3px;"></span>
                                        </button>

                                        <div class="dropdown-menu dropdown-menu-right" style="min-width: 320px; padding: 15px;" @click.stop="">
                                            <div class="form-group">
                                                <label>{{ jsToLang('card.graphs.custom_range.start_date') || 'Start Date' }}</label>
                                                <div class="row">
                                                    <div class="col-md-6" style="padding-right: 5px;">
                                                        <input type="date" class="form-control" v-model="customDateRange.dates.start" :max="new Date().toISOString().substr(0, 10)" :min="networkGraphs[visibleNetworkGraphPort]?.earliestDateSplitted">
                                                    </div>
                                                    <div class="col-md-6" style="padding-left: 5px;">
                                                        <input type="time" class="form-control" v-model="customDateRange.times.start">
                                                    </div>
                                                </div>
                                            </div>

                                            <div class="form-group">
                                                <label>{{ jsToLang('card.graphs.custom_range.end_date') || 'End Date' }}</label>
                                                <div class="row">
                                                    <div class="col-md-6" style="padding-right: 5px;">
                                                        <input type="date" class="form-control" v-model="customDateRange.dates.end" :max="new Date().toISOString().substr(0, 10)" :min="customDateRange.dates.start">
                                                    </div>
                                                    <div class="col-md-6" style="padding-left: 5px;">
                                                        <input type="time" class="form-control" v-model="customDateRange.times.end">
                                                    </div>
                                                </div>
                                            </div>

                                            <div class="text-right">
                                                <button type="button" class="btn btn-default btn-sm" @click.stop="closeCustomDateDropdown()">
                                                    {{ jsToLang('generic.button.cancel') || 'Cancel' }}
                                                </button>
                                                <button type="button" class="btn btn-primary btn-sm" @click.stop="applyCustomDateRange()" :disabled="!isValidDateRange">
                                                    {{ jsToLang('generic.button.submit') || 'Submit' }}
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <template v-for="(v, k) in networkGraphs">
                                <template v-if="visibleNetworkGraphPort === k">
                                    <template v-if="v.options">
                                        <apexchart :key="'networkGraphk' + k" width="100%" height="300px" type="area" :options="v.options" :series="v.series"></apexchart>

                                        <div style="margin-bottom: 10px;">
                                            <button type="button" class="btn btn-default btn-sm" @click="networkStatsShowDetails = !networkStatsShowDetails;">
                                                <i :class="networkStatsShowDetails ? faIconRepo('fa-eye-slash') : faIconRepo('fa-eye')" style="margin-right: 3px;"></i>
                                                {{ networkStatsShowDetails ? jsToLang('card.graphs.button.hide_summary') : jsToLang('card.graphs.button.show_summary') }}
                                            </button>

                                            <table class="table ds-table-no-top-border ds-table-td-vertical" :style="$simpleStore.getLoader('generateBandwidthCharts') ? 'opacity: 0.5' : 'opacity: 1.0'" v-if="networkStatsShowDetails"
                                                   style="margin-bottom: 0;">
                                                <thead>
                                                <tr>
                                                    <th>{{ jsToLang('card.graphs.table.summary.head.direction') }}</th>
                                                    <th>{{ jsToLang('card.graphs.table.summary.head.volume') }}</th>
                                                    <th>{{ jsToLang('card.graphs.table.summary.head.current') }}</th>
                                                    <th>{{ jsToLang('card.graphs.table.summary.head.average') }}</th>
                                                    <th>{{ jsToLang('card.graphs.table.summary.head.p95th') }}</th>
                                                </tr>
                                                </thead>
                                                <tbody>
                                                <tr>
                                                    <td>
                                                        <b>{{ jsToLang('card.graphs.table.summary.column.in') }}</b>
                                                    </td>
                                                    <td>{{ formatBitToGb(v.summary.transfer.in) }} GB</td>
                                                    <td>{{ v.summary.bwrate.lastIn }} MBit/s</td>
                                                    <td>{{ v.summary.bwrate.avgIn }} MBit/s</td>
                                                    <td>{{ v.summary.bwrate.p95thIn }} MBit/s</td>
                                                </tr>
                                                <tr>
                                                    <td>
                                                        <b>{{ jsToLang('card.graphs.table.summary.column.out') }}</b>
                                                    </td>
                                                    <td>{{ formatBitToGb(v.summary.transfer.out) }} GB</td>
                                                    <td>{{ v.summary.bwrate.lastOut }} MBit/s</td>
                                                    <td>{{ v.summary.bwrate.avgOut }} MBit/s</td>
                                                    <td>{{ v.summary.bwrate.p95thOut }} MBit/s</td>
                                                </tr>
                                                <tr>
                                                    <td>
                                                        <b>{{ jsToLang('card.graphs.table.summary.column.total') }}</b>
                                                    </td>
                                                    <td>{{ formatBitToGb(v.summary.transfer.total) }} GB</td>
                                                    <td>{{ v.summary.bwrate.lastTotal }} MBit/s</td>
                                                    <td>{{ v.summary.bwrate.avgTotal }} MBit/s</td>
                                                    <td>{{ v.summary.bwrate.p95thTotal }} MBit/s</td>
                                                </tr>
                                                </tbody>
                                            </table>
                                        </div>
                                    </template>

                                    <template v-if="v.graphType && v.graphImageData !== ''">
                                        <img style="margin-top: 5px; margin-bottom: 5px;" class="img-responsive center-block mx-auto d-block img-fluid" :src="'data:' + v.graphType + ';base64, ' + v.graphImageData"
                                             :style="v.imgWidth ? 'width: ' + v.imgWidth : ''">
                                    </template>
                                </template>
                            </template>
                        </template>
                    </div>

                    <div v-if="graphTabSelection === 'resources'">
                        <template v-if="$simpleStore.getLoader('atLeastOneResourceGraphLoaded')">
                            <div class="text-center">
                                <i style="font-size: 24px;" :class="faIconRepo('fa-refresh-spin')"></i>
                            </div>
                        </template>

                        <div v-if="resourceGraphs.cpu.length > 0 && statsAvailability.cpu !== 0" style="margin-bottom: 30px;">
                            <template v-for="(cpu, index) in resourceGraphs.cpu">
                                <div :key="'cpuGraph_' + index" style="margin-bottom: 20px;">
                                    <div style="margin-bottom: 10px;">
                                        <b style="font-size: 20px; font-weight: 500;">{{ jsToLang('card.graphs.resource.cpu.title') || 'CPU' }}</b>

                                        <div class="btn-group pull-right float-md-right" role="group" aria-label="Select timerange">
                                            <button v-for="(v, k) in cpu?.features?.availablePredefinedValues" :key="'cpuRangeSelector_' + k" :disabled="$simpleStore.getLoader('getCpuGraphs') || v.available === 0" @click="getCpuGraphs(v.submitValue)"
                                                    type="button" class="btn" :class="[resourceTimeframes.cpu === v.submitValue ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']">
                                                <span data-toggle="dynamic-tooltip" :title="v.available === 0 ? jsToLang('card.graphs.button.timerange.not_available_because_of_owner_date') : ''">
                                                    {{ v.lang }}
                                                </span>
                                            </button>

                                            <!-- CPU Custom Date Range -->
                                            <div class="btn-group" style="display: inline-block;" v-if="cpu?.features?.customRangeAvailable === 1">
                                                <button type="button" class="btn dropdown-toggle" :class="[resourceCustomDateRanges.cpu.isActive ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']" data-toggle="dropdown"
                                                        aria-haspopup="true" aria-expanded="false" :disabled="$simpleStore.getLoader('getCpuGraphs') === 1">
                                                    <i :class="faIconRepo('fa-calendar-alt')" style="margin-right: 3px;"></i>
                                                    {{ jsToLang('card.graphs.button.timerange.custom') || 'Custom' }}
                                                    <span class="caret" style="margin-left: 3px;"></span>
                                                </button>

                                                <div class="dropdown-menu dropdown-menu-right" style="min-width: 320px; padding: 15px;" @click.stop="">
                                                    <div class="form-group">
                                                        <label>{{ jsToLang('card.graphs.custom_range.start_date') || 'Start Date' }}</label>
                                                        <div class="row">
                                                            <div class="col-md-6" style="padding-right: 5px;">
                                                                <input type="date" class="form-control" v-model="resourceCustomDateRanges.cpu.dates.start" :max="new Date().toISOString().substr(0, 10)" :min="cpu?.earliestDateSplitted">
                                                            </div>
                                                            <div class="col-md-6" style="padding-left: 5px;">
                                                                <input type="time" class="form-control" v-model="resourceCustomDateRanges.cpu.times.start">
                                                            </div>
                                                        </div>
                                                    </div>

                                                    <div class="form-group">
                                                        <label>{{ jsToLang('card.graphs.custom_range.end_date') || 'End Date' }}</label>
                                                        <div class="row">
                                                            <div class="col-md-6" style="padding-right: 5px;">
                                                                <input type="date" class="form-control" v-model="resourceCustomDateRanges.cpu.dates.end" :max="new Date().toISOString().substr(0, 10)" :min="resourceCustomDateRanges.cpu.dates.start">
                                                            </div>
                                                            <div class="col-md-6" style="padding-left: 5px;">
                                                                <input type="time" class="form-control" v-model="resourceCustomDateRanges.cpu.times.end">
                                                            </div>
                                                        </div>
                                                    </div>

                                                    <div class="text-right">
                                                        <button type="button" class="btn btn-default btn-sm" @click.stop="closeCustomDateDropdown">
                                                            {{ jsToLang('generic.button.cancel') || 'Cancel' }}
                                                        </button>
                                                        <button type="button" class="btn btn-primary btn-sm" @click.stop="applyResourceCustomDateRange('cpu')" :disabled="!isResourceValidDateRange('cpu')">
                                                            {{ jsToLang('generic.button.submit') || 'Submit' }}
                                                        </button>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>

                                    <apexchart :style="$simpleStore.getLoader('getCpuGraphs') ? 'opacity: 0.5' : 'opacity: 1.0'" width="100%" height="300px" type="area" :options="cpu.options" :series="cpu.series"></apexchart>
                                </div>
                            </template>
                        </div>

                        <div v-if="resourceGraphs.memory.length > 0 && statsAvailability.memory !== 0" style="margin-bottom: 30px;">
                            <template v-for="(memory, index) in resourceGraphs.memory">
                                <div :key="'memoryGraph_' + index" style="margin-bottom: 20px;">
                                    <div style="margin-bottom: 10px;">
                                        <b style="font-size: 20px; font-weight: 500;">{{ jsToLang('card.graphs.resource.memory.title') || 'Memory' }}</b>

                                        <div class="btn-group pull-right float-md-right" role="group" aria-label="Select timerange">
                                            <button v-for="(v, k) in memory?.features?.availablePredefinedValues" :key="'memoryRangeSelector_' + k" :disabled="$simpleStore.getLoader('getMemoryGraphs') || v.available === 0"
                                                    @click="getMemoryGraphs(v.submitValue)" type="button" class="btn" :class="[resourceTimeframes.memory === v.submitValue ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']">
                                                <span data-toggle="dynamic-tooltip" :title="v.available === 0 ? jsToLang('card.graphs.button.timerange.not_available_because_of_owner_date') : ''">
                                                    {{ v.lang }}
                                                </span>
                                            </button>

                                            <!-- Memory Custom Date Range -->
                                            <div class="btn-group" style="display: inline-block;" v-if="memory?.features?.customRangeAvailable === 1">
                                                <button type="button" class="btn dropdown-toggle" :class="[resourceCustomDateRanges.memory.isActive ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']" data-toggle="dropdown"
                                                        aria-haspopup="true" aria-expanded="false" :disabled="$simpleStore.getLoader('getMemoryGraphs') === 1">
                                                    <i :class="faIconRepo('fa-calendar-alt')" style="margin-right: 3px;"></i>
                                                    {{ jsToLang('card.graphs.button.timerange.custom') || 'Custom' }}
                                                    <span class="caret" style="margin-left: 3px;"></span>
                                                </button>

                                                <div class="dropdown-menu dropdown-menu-right" style="min-width: 320px; padding: 15px;" @click.stop="">
                                                    <div class="form-group">
                                                        <label>{{ jsToLang('card.graphs.custom_range.start_date') || 'Start Date' }}</label>
                                                        <div class="row">
                                                            <div class="col-md-6" style="padding-right: 5px;">
                                                                <input type="date" class="form-control" v-model="resourceCustomDateRanges.memory.dates.start" :max="new Date().toISOString().substr(0, 10)" :min="memory?.earliestDateSplitted">
                                                            </div>
                                                            <div class="col-md-6" style="padding-left: 5px;">
                                                                <input type="time" class="form-control" v-model="resourceCustomDateRanges.memory.times.start">
                                                            </div>
                                                        </div>
                                                    </div>

                                                    <div class="form-group">
                                                        <label>{{ jsToLang('card.graphs.custom_range.end_date') || 'End Date' }}</label>
                                                        <div class="row">
                                                            <div class="col-md-6" style="padding-right: 5px;">
                                                                <input type="date" class="form-control" v-model="resourceCustomDateRanges.memory.dates.end" :max="new Date().toISOString().substr(0, 10)"
                                                                       :min="resourceCustomDateRanges.memory.dates.start">
                                                            </div>
                                                            <div class="col-md-6" style="padding-left: 5px;">
                                                                <input type="time" class="form-control" v-model="resourceCustomDateRanges.memory.times.end">
                                                            </div>
                                                        </div>
                                                    </div>

                                                    <div class="text-right">
                                                        <button type="button" class="btn btn-default btn-sm" @click.stop="closeCustomDateDropdown">
                                                            {{ jsToLang('generic.button.cancel') || 'Cancel' }}
                                                        </button>
                                                        <button type="button" class="btn btn-primary btn-sm" @click.stop="applyResourceCustomDateRange('memory')" :disabled="!isResourceValidDateRange('memory')">
                                                            {{ jsToLang('generic.button.submit') || 'Submit' }}
                                                        </button>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>

                                    <apexchart :style="$simpleStore.getLoader('getMemoryGraphs') ? 'opacity: 0.5' : 'opacity: 1.0'" width="100%" height="300px" type="area" :options="memory.options" :series="memory.series"></apexchart>
                                </div>
                            </template>
                        </div>

                        <div v-if="resourceGraphs.diskio.length > 0 && statsAvailability.diskio !== 0" style="margin-bottom: 30px;">
                            <template v-for="(diskio, index) in resourceGraphs.diskio">
                                <div :key="'diskioGraph_' + index" style="margin-bottom: 20px;">
                                    <div style="margin-bottom: 10px;">
                                        <b style="font-size: 20px; font-weight: 500;">{{ jsToLang('card.graphs.resource.diskio.title') || 'Disk I/O' }}</b>

                                        <div class="btn-group pull-right float-md-right" role="group" aria-label="Select timerange">
                                            <button v-for="(v, k) in diskio?.features?.availablePredefinedValues" :key="'diskioRangeSelector_' + k" :disabled="$simpleStore.getLoader('getDiskIoGraphs') || v.available === 0"
                                                    @click="getDiskIoGraphs(v.submitValue)" type="button" class="btn" :class="[resourceTimeframes.diskio === v.submitValue ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']">
                                                <span data-toggle="dynamic-tooltip" :title="v.available === 0 ? jsToLang('card.graphs.button.timerange.not_available_because_of_owner_date') : ''">
                                                    {{ v.lang }}
                                                </span>
                                            </button>

                                            <!-- Disk I/O Custom Date Range -->
                                            <div class="btn-group" style="display: inline-block;" v-if="diskio?.features?.customRangeAvailable === 1">
                                                <button type="button" class="btn dropdown-toggle" :class="[resourceCustomDateRanges.diskio.isActive ? 'btn-primary' : 'btn-default', getBsVersion !== 3 ? 'btn-sm' : '']" data-toggle="dropdown"
                                                        aria-haspopup="true" aria-expanded="false" :disabled="$simpleStore.getLoader('getDiskIoGraphs') === 1">
                                                    <i :class="faIconRepo('fa-calendar-alt')" style="margin-right: 3px;"></i>
                                                    {{ jsToLang('card.graphs.button.timerange.custom') || 'Custom' }}
                                                    <span class="caret" style="margin-left: 3px;"></span>
                                                </button>

                                                <div class="dropdown-menu dropdown-menu-right" style="min-width: 320px; padding: 15px;" @click.stop="">
                                                    <div class="form-group">
                                                        <label>{{ jsToLang('card.graphs.custom_range.start_date') || 'Start Date' }}</label>
                                                        <div class="row">
                                                            <div class="col-md-6" style="padding-right: 5px;">
                                                                <input type="date" class="form-control" v-model="resourceCustomDateRanges.diskio.dates.start" :max="new Date().toISOString().substr(0, 10)" :min="diskio?.earliestDateSplitted">
                                                            </div>
                                                            <div class="col-md-6" style="padding-left: 5px;">
                                                                <input type="time" class="form-control" v-model="resourceCustomDateRanges.diskio.times.start">
                                                            </div>
                                                        </div>
                                                    </div>

                                                    <div class="form-group">
                                                        <label>{{ jsToLang('card.graphs.custom_range.end_date') || 'End Date' }}</label>
                                                        <div class="row">
                                                            <div class="col-md-6" style="padding-right: 5px;">
                                                                <input type="date" class="form-control" v-model="resourceCustomDateRanges.diskio.dates.end" :max="new Date().toISOString().substr(0, 10)"
                                                                       :min="resourceCustomDateRanges.diskio.dates.start">
                                                            </div>
                                                            <div class="col-md-6" style="padding-left: 5px;">
                                                                <input type="time" class="form-control" v-model="resourceCustomDateRanges.diskio.times.end">
                                                            </div>
                                                        </div>
                                                    </div>

                                                    <div class="text-right">
                                                        <button type="button" class="btn btn-default btn-sm" @click.stop="closeCustomDateDropdown">
                                                            {{ jsToLang('generic.button.cancel') || 'Cancel' }}
                                                        </button>
                                                        <button type="button" class="btn btn-primary btn-sm" @click.stop="applyResourceCustomDateRange('diskio')" :disabled="!isResourceValidDateRange('diskio')">
                                                            {{ jsToLang('generic.button.submit') || 'Submit' }}
                                                        </button>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>

                                    <apexchart :style="$simpleStore.getLoader('getDiskIoGraphs') ? 'opacity: 0.5' : 'opacity: 1.0'" width="100%" height="300px" type="area" :options="diskio.options" :series="diskio.series"></apexchart>
                                </div>
                            </template>
                        </div>
                    </div>
                </div>
            </div>
        </template>
    `,

    components: {
        'apexchart': window.VueApexCharts,
    },

    computed: {
        hasResourceGraphs: function () {
            return (this.dCan('servers.stats.cpu') || this.dCan('servers.stats.memory') || this.dCan('servers.stats.diskio'));
        },

        hasAvailableNetworkStats: function () {
            return this.statsAvailability.network === 1;
        },

        hasAvailableResourceStats: function () {
            return this.statsAvailability.cpu === 1 || this.statsAvailability.memory === 1 || this.statsAvailability.diskio === 1;
        },

        shouldShowGraphsCard: function () {
            return this.hasAvailableNetworkStats || this.hasAvailableResourceStats;
        },

        shouldShowNetworkTab: function () {
            return this.dCan('servers.stats.network') && this.hasAvailableNetworkStats;
        },

        shouldShowResourcesTab: function () {
            return this.hasResourceGraphs && this.hasAvailableResourceStats;
        },

        isValidDateRange: function () {
            if (!this.customDateRange.dates.start || !this.customDateRange.dates.end || !this.customDateRange.times.start || !this.customDateRange.times.end) {
                return false;
            }

            const startDateTime = new Date(`${this.customDateRange.dates.start}T${this.customDateRange.times.start}:00`);
            const endDateTime = new Date(`${this.customDateRange.dates.end}T${this.customDateRange.times.end}:00`);

            const minDateStr = this.networkGraphs[this.visibleNetworkGraphPort]?.earliestDateSplitted;

            const todayDateStr = new Date().toISOString().substr(0, 10);

            return !isNaN(startDateTime.getTime()) && !isNaN(endDateTime.getTime()) && startDateTime <= endDateTime && this.customDateRange.dates.start >= minDateStr && this.customDateRange.dates.end <= todayDateStr;
        }
    },

    async mounted() {
        if (this.networkGraphShowSummaryByDefault === 'yes') {
            this.networkStatsShowDetails = true;
        }

        if (this.dCan('servers.stats.getAvailableStatistics')) {
            await this.checkStatsAvailability();

            if (this.statsAvailability.network === 1) {
                this.generateBandwidthCharts();
            }

            if (this.hasAvailableResourceStats && this.graphTabSelection === 'resources') {
                this.loadAvailableResourceGraphs();
            }
        }
    },

    methods: {
        calculateNetworkSummary(stats, fromTimestamp = null, toTimestamp = null) {
            const summary = {
                transfer: {
                    in: 0,
                    out: 0,
                    total: 0,
                },
                bwrate: {
                    lastIn: 0,
                    lastOut: 0,
                    lastTotal: 0,
                    avgIn: 0,
                    avgOut: 0,
                    avgTotal: 0,
                    p95thIn: 0,
                    p95thOut: 0,
                    p95thTotal: 0,
                }
            };

            if (!stats || stats.length === 0) {
                return summary;
            }

            const seriesInData = [];
            const seriesOutData = [];

            let filteredStats = stats;
            if (fromTimestamp !== null && toTimestamp !== null) {
                if (!stats._processedTimestamps) {
                    stats._processedTimestamps = true;
                    stats.forEach(item => {
                        if (item.time) {
                            item._timeMs = new Date(item.time).getTime();
                        }
                    });
                }

                filteredStats = stats.filter(item => {
                    return item._timeMs >= fromTimestamp && item._timeMs <= toTimestamp;
                });
            }

            const dataToUse = filteredStats;

            if (dataToUse.length === 0) {
                return summary;
            }

            const inValues = [];
            const outValues = [];
            const totalValues = [];

            for (const item of dataToUse) {
                summary.transfer.in += item.traffic_in;
                summary.transfer.out += item.traffic_out;

                const inRate = parseFloat(item.bwrate_in);
                const outRate = parseFloat(item.bwrate_out);
                const totalRate = parseFloat(item.bwrate_total);

                inValues.push(inRate);
                outValues.push(outRate);
                totalValues.push(totalRate);

                seriesInData.push(this.formatBitToMbit(inRate));
                seriesOutData.push(this.formatBitToMbit(outRate));
            }

            summary.transfer.total = summary.transfer.in + summary.transfer.out;

            const combinedArr = seriesInData.concat(seriesOutData);
            summary.bwrate.avgIn = (seriesInData.reduce((a, b) => (parseFloat(a) + parseFloat(b)), 0) / seriesInData.length).toFixed(2);
            summary.bwrate.avgOut = (seriesOutData.reduce((a, b) => (parseFloat(a) + parseFloat(b)), 0) / seriesOutData.length).toFixed(2);
            summary.bwrate.avgTotal = (combinedArr.reduce((a, b) => (parseFloat(a) + parseFloat(b)), 0) / combinedArr.length).toFixed(2);

            if (dataToUse.length > 0) {
                const sortedInValues = [...inValues].sort((a, b) => a - b);
                const sortedOutValues = [...outValues].sort((a, b) => a - b);
                const sortedTotalValues = [...totalValues].sort((a, b) => a - b);

                const p95thInIndex = Math.max(0, Math.min(Math.ceil(0.95 * sortedInValues.length) - 1, sortedInValues.length - 1));
                const p95thOutIndex = Math.max(0, Math.min(Math.ceil(0.95 * sortedOutValues.length) - 1, sortedOutValues.length - 1));
                const p95thTotalIndex = Math.max(0, Math.min(Math.ceil(0.95 * sortedTotalValues.length) - 1, sortedTotalValues.length - 1));

                summary.bwrate.p95thIn = this.formatBitToMbit(sortedInValues[p95thInIndex]);
                summary.bwrate.p95thOut = this.formatBitToMbit(sortedOutValues[p95thOutIndex]);
                summary.bwrate.p95thTotal = this.formatBitToMbit(sortedTotalValues[p95thTotalIndex]);
            }

            if (dataToUse.length > 0) {
                const lastPoint = dataToUse[dataToUse.length - 1];
                summary.bwrate.lastIn = this.formatBitToMbit(lastPoint.bwrate_in);
                summary.bwrate.lastOut = this.formatBitToMbit(lastPoint.bwrate_out);
                summary.bwrate.lastTotal = this.formatBitToMbit(lastPoint.bwrate_total);
            }

            return summary;
        },

        recalculateNetworkSummaryAfterZoom(stats, min, max, portIndex) {
            if (!stats || stats.length === 0 || portIndex === undefined) {
                return;
            }

            clearTimeout(this._recalcTimeoutId);
            this._recalcTimeoutId = setTimeout(() => {
                const summary = this.calculateNetworkSummary(stats, min, max);

                const index = typeof portIndex === 'string' ? parseInt(portIndex) : portIndex;
                if (this.networkGraphs[index]) {
                    this.networkGraphs[index].summary = summary;

                    this.$set(this.networkGraphs, index, {...this.networkGraphs[index]});
                }
            }, 50);
        },

        async checkStatsAvailability(predefinedRange = '24h') {
            try {
                const response = await axios.post(this.xhrUrl + 'getAvailableStatistics', {
                    predefinedRange: predefinedRange
                });

                if (response?.data?.available) {
                    this.statsAvailability = {
                        network: 0,
                        cpu: 0,
                        memory: 0,
                        diskio: 0
                    };

                    response.data.available.forEach(stat => {
                        if (stat === 'bandwidth') {
                            this.statsAvailability.network = 1;
                        } else if (this.statsAvailability.hasOwnProperty(stat)) {
                            this.statsAvailability[stat] = 1;
                        }
                    });
                }

                this.setInitialTab();
            } catch (e) {
                console.error('Failed to check stats availability:', e);
            }
        },

        setInitialTab() {
            this.graphTabSelection = 'network';

            if (this.statsAvailability.network === 1) {
                this.graphTabSelection = 'network';
            } else if ((this.statsAvailability.cpu === 1 || this.statsAvailability.memory === 1 || this.statsAvailability.diskio === 1) && this.hasResourceGraphs) {
                this.graphTabSelection = 'resources';
            }
        },

        async generateBandwidthCharts(timerange = '24h', customTimeRange = null) {
            if (!this.dCan('servers.stats.network')) {
                return;
            }

            this.$simpleStore.addLoader('generateBandwidthCharts');

            try {
                let requestData = {};

                if (customTimeRange) {
                    this.customDateRange.isActive = true;
                    this.selectedNetworkGraphTimerange = 'custom';
                    requestData = {
                        from: customTimeRange.from,
                        to: customTimeRange.to
                    };
                } else {
                    this.customDateRange.isActive = false;
                    this.selectedNetworkGraphTimerange = timerange;
                    requestData = {predefinedRange: timerange};
                }

                const getData = await axios.post(this.xhrUrl + 'getNetworkgraphValues', requestData);

                this.networkGraphs = [];

                if (!getData?.data || Object.keys(getData.data).length === 0) {
                    this.statsAvailability.network = 0;
                    return false;
                }

                for (const [key, value] of Object.entries(getData.data)) {
                    if (value.graphImageData) {
                        value.portName = key + 1;
                        var graphData = value;
                    } else if (value.stats && value.stats.length) {
                        const self = this;
                        const portIndex = key;
                        const portStats = value.stats;

                        var graphData = {
                            features: value.features,
                            earliestDateSplitted: value?.earliestDate?.split(' ')[0] || '2020-01-01',
                            portName: value.name ? value.name : key + 1,
                            stats: value.stats,
                            options: {
                                chart: {
                                    type: 'area',
                                    animations: {
                                        enabled: false,
                                    },
                                    zoom: {
                                        enabled: true,
                                        type: 'x',
                                        autoScaleYaxis: true,
                                        zoomedArea: {
                                            fill: {
                                                color: '#90CAF9',
                                                opacity: 0.4
                                            },
                                            stroke: {
                                                color: '#0D47A1',
                                                opacity: 0.4,
                                                width: 1
                                            }
                                        }
                                    },
                                    events: {
                                        zoomed: function (chartContext, {xaxis}) {
                                            if (self.isResettingZoom.network) {
                                                self.isResettingZoom.network = false;
                                                return;
                                            }

                                            self.graphZoomStatus.network = true;
                                            if (xaxis && xaxis.min && xaxis.max) {
                                                self.recalculateNetworkSummaryAfterZoom(portStats, xaxis.min, xaxis.max, portIndex);
                                            }
                                        },
                                        beforeResetZoom: function () {
                                            self.isResettingZoom.network = true;
                                            self.graphZoomStatus.network = false;
                                            self.recalculateNetworkSummaryAfterZoom(portStats, null, null, portIndex);
                                        },
                                        scrolled: function (chartContext, {xaxis}) {
                                            if (xaxis && xaxis.min && xaxis.max) {
                                                self.recalculateNetworkSummaryAfterZoom(portStats, xaxis.min, xaxis.max, portIndex);
                                            }
                                        }
                                    },
                                },
                                xaxis: {
                                    type: 'datetime',
                                    categories: [],
                                    labels: {
                                        datetimeUTC: false
                                    }
                                },
                                tooltip: {
                                    y: {
                                        formatter: function (value, opts) {
                                            return value + ' Mbit/s';
                                        },
                                    },
                                    x: {
                                        format: 'dd MMM, HH:mm'
                                    }
                                },
                                yaxis: {
                                    labels: {
                                        show: true,
                                        formatter: (value) => {
                                            return value.toFixed(2) + ' Mbit/s'
                                        },
                                    },
                                },
                                stroke: {
                                    width: 2
                                },
                                dataLabels: {
                                    enabled: false,
                                }
                            },
                            series: [
                                {
                                    type: 'area',
                                    name: 'In',
                                    data: [],
                                },
                                {
                                    name: 'Out',
                                    type: 'area',
                                    data: []
                                }
                            ],
                            summary: {
                                transfer: {
                                    in: 0,
                                    out: 0,
                                    total: 0,
                                },
                                bwrate: {
                                    lastIn: 0,
                                    lastOut: 0,
                                    lastTotal: 0,
                                    avgIn: 0,
                                    avgOut: 0,
                                    avgTotal: 0,
                                    p95thIn: 0,
                                    p95thOut: 0,
                                    p95thTotal: 0,
                                }
                            }
                        };

                        const dataToUse = this.downsampleData(value.stats, 5500, 160 * 60);

                        for (const dataPoint of dataToUse) {
                            graphData.options.xaxis.categories.push(dataPoint.time);
                            graphData.series[0].data.push(this.formatBitToMbit(dataPoint.bwrate_in));
                            graphData.series[1].data.push(this.formatBitToMbit(dataPoint.bwrate_out));
                        }

                        graphData.summary = this.calculateNetworkSummary(value.stats);
                    } else {
                        continue;
                    }

                    if (!graphData.summary) {
                        graphData.summary = {
                            transfer: {
                                in: 0,
                                out: 0,
                                total: 0,
                            },
                            bwrate: {
                                lastIn: 0,
                                lastOut: 0,
                                lastTotal: 0,
                                avgIn: 0,
                                avgOut: 0,
                                avgTotal: 0,
                                p95thIn: 0,
                                p95thOut: 0,
                                p95thTotal: 0,
                            }
                        };
                    }

                    if (this.networkGraphShowp95thLineByDefault === 'yes') {
                        graphData.options.annotations = {
                            yaxis: [
                                {
                                    y: graphData.summary.bwrate.p95thTotal,
                                    borderColor: 'red',
                                    borderWidth: 1,
                                    strokeDashArray: 0,
                                    label: {
                                        borderColor: "#FF4560",
                                        offsetY: 0,
                                        offsetX: 25,
                                        style: {
                                            color: "#fff",
                                            background: "#e60000",
                                        },
                                        position: 'left',
                                        text: "95th"
                                    }
                                },
                            ],
                        };
                    }

                    if (value.selectedPredefinedTimerange && value.selectedPredefinedTimerange !== '') {
                        this.selectedNetworkGraphTimerange = value.selectedPredefinedTimerange;
                    }

                    this.networkGraphs.push(graphData);
                }
            } catch (e) {
                console.log('Error during requesting network graph (usually, you can ignore this message). Reason: ' + e.response?.data + ' | ' + e);
                return false;
            } finally {
                this.$simpleStore.delLoader('generateBandwidthCharts');
            }
        },

        fillDataGaps(data, maxGapSeconds) {
            if (!data || data.length < 2) {
                return data;
            }

            const result = [];
            result.push(data[0]);

            for (let i = 1; i < data.length; i++) {
                const prevTime = new Date(data[i - 1].time).getTime();
                const currTime = new Date(data[i].time).getTime();
                const gapSeconds = (currTime - prevTime) / 1000;

                if (gapSeconds > maxGapSeconds) {
                    const nullPoint1 = {time: null};
                    const nullPoint2 = {time: null};

                    for (const key in data[i]) {
                        if (key !== 'time') {
                            nullPoint1[key] = null;
                            nullPoint2[key] = null;
                        }
                    }

                    nullPoint1.time = new Date(prevTime + 1000).toISOString();
                    nullPoint2.time = new Date(currTime - 1000).toISOString();

                    result.push(nullPoint1);
                    result.push(nullPoint2);
                }

                result.push(data[i]);
            }

            return result;
        },

        downsampleData(data, maxPoints = 5000, maxGapSeconds = null) {
            if (!data || data.length === 0) {
                return data;
            }

            let processedData = data;
            if (maxGapSeconds !== null && maxGapSeconds > 0) {
                processedData = this.fillDataGaps(data, maxGapSeconds);
            }

            if (processedData.length <= maxPoints) {
                return processedData;
            }

            const step = Math.max(1, Math.floor(processedData.length / maxPoints));

            const downsampled = [];

            downsampled.push(processedData[0]);

            for (let i = step; i < processedData.length - 1; i += step) {
                downsampled.push(processedData[i]);
            }

            if (processedData.length > 1) {
                downsampled.push(processedData[processedData.length - 1]);
            }

            return downsampled;
        },

        formatBitToMbit(bit, decimals = 2) {
            if (bit === 0) {
                return 0;
            }

            if (decimals === '') {
                decimals = 2;
            }

            const mbit = bit / 1048576;

            return mbit.toFixed(decimals);
        },

        formatBitToGb(bit) {
            if (bit === 0) {
                return 0;
            }

            const gb = bit / 1073741824;
            return gb.toFixed(2);
        },

        async applyCustomDateRange() {
            if (!this.isValidDateRange) {
                return;
            }

            const fromDateTime = `${this.customDateRange.dates.start}T${this.customDateRange.times.start}:00Z`;
            const toDateTime = `${this.customDateRange.dates.end}T${this.customDateRange.times.end}:00Z`;

            await this.generateBandwidthCharts(null, {
                from: fromDateTime,
                to: toDateTime
            });

            this.closeCustomDateDropdown();
        },

        closeCustomDateDropdown() {
            jQuery(this.$el).find('.btn-group.open').removeClass('open');
            jQuery(this.$el).find('.dropdown-menu').removeClass('show');
        },

        switchToResourcesTab() {
            this.graphTabSelection = 'resources';

            const needsLoading = (this.statsAvailability.cpu === 1 && this.resourceGraphs.cpu.length === 0) || (this.statsAvailability.memory === 1 && this.resourceGraphs.memory.length === 0) || (this.statsAvailability.diskio === 1 && this.resourceGraphs.diskio.length === 0);

            if (needsLoading) {
                this.loadAvailableResourceGraphs();
            }
        },

        async loadAvailableResourceGraphs() {
            this.$simpleStore.addLoader('atLeastOneResourceGraphLoaded');

            if (this.statsAvailability.cpu === 1 && this.dCan('servers.stats.cpu')) {
                this.getCpuGraphs();
            }

            if (this.statsAvailability.memory === 1 && this.dCan('servers.stats.memory')) {
                this.getMemoryGraphs();
            }

            if (this.statsAvailability.diskio === 1 && this.dCan('servers.stats.diskio')) {
                this.getDiskIoGraphs();
            }

            setTimeout(() => {
                this.$simpleStore.delLoader('atLeastOneResourceGraphLoaded');
            }, 1000);
        },

        async getCpuGraphs(timerange = '24h', customTimeRange = null) {
            this.$simpleStore.addLoader('getCpuGraphs');

            try {
                let requestData = {
                    resourceType: 'cpu',
                    statType: 'graph'
                };

                if (customTimeRange) {
                    this.resourceCustomDateRanges.cpu.isActive = true;
                    this.resourceTimeframes.cpu = 'custom';
                    requestData.from = customTimeRange.from;
                    requestData.to = customTimeRange.to;
                } else {
                    this.resourceCustomDateRanges.cpu.isActive = false;
                    this.resourceTimeframes.cpu = timerange;
                    requestData.predefinedRange = timerange;
                }

                const getData = await axios.post(this.xhrUrl + 'getResourceStatistics', requestData);

                this.resourceGraphs.cpu = [];

                if (!getData?.data || Object.keys(getData.data).length === 0) {
                    this.statsAvailability.cpu = 0;  // Markiere als nicht verfügbar
                    return false;
                }

                for (const [key, value] of Object.entries(getData.data)) {
                    if (value.stats && value.stats.length) {
                        const graphData = {
                            features: value.features,
                            earliestDateSplitted: value?.earliestDate?.split(' ')[0] || '2020-01-01',
                            name: value.name || `CPU ${key + 1}`,
                            options: {
                                chart: {
                                    type: 'area',
                                    animations: {enabled: false},
                                    zoom: {
                                        enabled: true,
                                        type: 'x',
                                        autoScaleYaxis: true,
                                        zoomedArea: {
                                            fill: {
                                                color: '#90CAF9',
                                                opacity: 0.4
                                            },
                                            stroke: {
                                                color: '#0D47A1',
                                                opacity: 0.4,
                                                width: 1
                                            }
                                        }
                                    },
                                },
                                xaxis: {
                                    type: 'datetime',
                                    categories: [],
                                    labels: {datetimeUTC: false}
                                },
                                tooltip: {
                                    y: {
                                        formatter: function (value) {
                                            return value.toFixed(2) + '%';
                                        }
                                    },
                                    x: {format: 'dd MMM, HH:mm'}
                                },
                                yaxis: {
                                    min: 0,
                                    max: 100,
                                    labels: {
                                        formatter: (value) => value.toFixed(0) + '%'
                                    }
                                },
                                stroke: {width: 2},
                                dataLabels: {enabled: false}
                            },
                            series: [
                                {
                                    name: 'CPU Usage',
                                    data: []
                                }
                            ]
                        };

                        const dataToUse = this.downsampleData(value.stats, 5500, 61 * 60);

                        for (const dataPoint of dataToUse) {
                            graphData.options.xaxis.categories.push(dataPoint.time);
                            graphData.series[0].data.push(parseFloat(dataPoint.cpuUsage || 0));
                        }

                        this.resourceGraphs.cpu.push(graphData);
                    }
                }
            } catch (e) {
                console.log('Error requesting CPU graph: ' + e);
                return false;
            } finally {
                this.$simpleStore.delLoader('getCpuGraphs');
                this.$simpleStore.delLoader('atLeastOneResourceGraphLoaded');
            }
        },

        async getMemoryGraphs(timerange = '24h', customTimeRange = null) {
            this.$simpleStore.addLoader('getMemoryGraphs');

            try {
                let requestData = {
                    resourceType: 'memory',
                    statType: 'graph'
                };

                if (customTimeRange) {
                    this.resourceCustomDateRanges.memory.isActive = true;
                    this.resourceTimeframes.memory = 'custom';
                    requestData.from = customTimeRange.from;
                    requestData.to = customTimeRange.to;
                } else {
                    this.resourceCustomDateRanges.memory.isActive = false;
                    this.resourceTimeframes.memory = timerange;
                    requestData.predefinedRange = timerange;
                }

                const getData = await axios.post(this.xhrUrl + 'getResourceStatistics', requestData);

                this.resourceGraphs.memory = [];

                if (!getData?.data || Object.keys(getData.data).length === 0) {
                    this.statsAvailability.memory = 0;
                    return false;
                }

                for (const [key, value] of Object.entries(getData.data)) {
                    if (value.stats && value.stats.length) {
                        let maxMemory = 0;
                        for (const stat of value.stats) {
                            if (stat.memoryTotal && parseInt(stat.memoryTotal) > maxMemory) {
                                maxMemory = parseInt(stat.memoryTotal);
                            }
                        }

                        const graphData = {
                            features: value.features,
                            earliestDateSplitted: value?.earliestDate?.split(' ')[0] || '2020-01-01',
                            name: value.name || `Memory ${key + 1}`,
                            options: {
                                chart: {
                                    type: 'area',
                                    animations: {enabled: false},
                                    zoom: {
                                        enabled: true,
                                        type: 'x',
                                        autoScaleYaxis: true,
                                        zoomedArea: {
                                            fill: {
                                                color: '#90CAF9',
                                                opacity: 0.4
                                            },
                                            stroke: {
                                                color: '#0D47A1',
                                                opacity: 0.4,
                                                width: 1
                                            }
                                        }
                                    },
                                },
                                xaxis: {
                                    type: 'datetime',
                                    categories: [],
                                    labels: {datetimeUTC: false}
                                },
                                tooltip: {
                                    y: {
                                        formatter: function (value) {
                                            return (value / 1000 / 1000 / 1000).toFixed(2) + ' GB';
                                        }
                                    },
                                    x: {format: 'dd MMM, HH:mm'}
                                },
                                yaxis: {
                                    min: 0,
                                    max: maxMemory,
                                    labels: {
                                        formatter: (value) => (value / 1000 / 1000 / 1000).toFixed(2) + ' GB'
                                    }
                                },
                                stroke: {width: 2},
                                dataLabels: {enabled: false}
                            },
                            series: [
                                {
                                    name: 'Memory Usage',
                                    data: []
                                }
                            ]
                        };

                        const dataToUse = this.downsampleData(value.stats, 5500, 61 * 60);

                        for (const dataPoint of dataToUse) {
                            graphData.options.xaxis.categories.push(dataPoint.time);
                            graphData.series[0].data.push(parseInt(dataPoint.memoryUsage || 0));
                        }

                        this.resourceGraphs.memory.push(graphData);
                    }
                }
            } catch (e) {
                console.log('Error requesting Memory graph: ' + e);
                return false;
            } finally {
                this.$simpleStore.delLoader('getMemoryGraphs');
                this.$simpleStore.delLoader('atLeastOneResourceGraphLoaded');
            }
        },

        async getDiskIoGraphs(timerange = '24h', customTimeRange = null) {
            this.$simpleStore.addLoader('getDiskIoGraphs');

            try {
                let requestData = {
                    resourceType: 'diskio',
                    statType: 'graph'
                };

                if (customTimeRange) {
                    this.resourceCustomDateRanges.diskio.isActive = true;
                    this.resourceTimeframes.diskio = 'custom';
                    requestData.from = customTimeRange.from;
                    requestData.to = customTimeRange.to;
                } else {
                    this.resourceCustomDateRanges.diskio.isActive = false;
                    this.resourceTimeframes.diskio = timerange;
                    requestData.predefinedRange = timerange;
                }

                const getData = await axios.post(this.xhrUrl + 'getResourceStatistics', requestData);

                this.resourceGraphs.diskio = [];

                if (!getData?.data || Object.keys(getData.data).length === 0) {
                    this.statsAvailability.diskio = 0;
                    return false;
                }

                for (const [key, value] of Object.entries(getData.data)) {
                    if (value.stats && value.stats.length) {
                        const graphData = {
                            features: value.features,
                            earliestDateSplitted: value?.earliestDate?.split(' ')[0] || '2020-01-01',
                            name: value.name || `Disk ${key + 1}`,
                            options: {
                                chart: {
                                    type: 'area',
                                    animations: {enabled: false},
                                    zoom: {
                                        enabled: true,
                                        type: 'x',
                                        autoScaleYaxis: true,
                                        zoomedArea: {
                                            fill: {
                                                color: '#90CAF9',
                                                opacity: 0.4
                                            },
                                            stroke: {
                                                color: '#0D47A1',
                                                opacity: 0.4,
                                                width: 1
                                            }
                                        }
                                    },
                                },
                                xaxis: {
                                    type: 'datetime',
                                    categories: [],
                                    labels: {datetimeUTC: false}
                                },
                                tooltip: {
                                    formatter: (v) => {
                                        const diskIoSizes = [
                                            'B/s',
                                            'KB/s',
                                            'MB/s',
                                            'GB/s',
                                            'TB/s'
                                        ];

                                        return this.formatByteToNice(v, 2, false, false, '0 B/s', diskIoSizes, true);
                                    },
                                    x: {format: 'dd MMM, HH:mm'}
                                },
                                yaxis: {
                                    labels: {
                                        show: true,
                                        formatter: (v) => {
                                            if (v === null || v === undefined || isNaN(v)) {
                                                return '';
                                            }

                                            const diskIoSizes = [
                                                'B/s',
                                                'KB/s',
                                                'MB/s',
                                                'GB/s',
                                                'TB/s'
                                            ];

                                            return this.formatByteToNice(v, 2, false, false, '0 B/s', diskIoSizes, true);
                                        },
                                    },
                                    min: 0,
                                },
                                stroke: {width: 2},
                                dataLabels: {enabled: false}
                            },
                            series: [
                                {
                                    name: 'Read',
                                    data: []
                                },
                                {
                                    name: 'Write',
                                    data: []
                                }
                            ]
                        };

                        const dataToUse = this.downsampleData(value.stats, 5500, 61 * 60);

                        for (const dataPoint of dataToUse) {
                            graphData.options.xaxis.categories.push(dataPoint.time);
                            graphData.series[0].data.push(parseFloat(dataPoint.diskRead || 0));
                            graphData.series[1].data.push(parseFloat(dataPoint.diskWrite || 0));
                        }

                        this.resourceGraphs.diskio.push(graphData);
                    }
                }
            } catch (e) {
                console.log('Error requesting Disk I/O graph: ' + e);
                return false;
            } finally {
                this.$simpleStore.delLoader('getDiskIoGraphs');
                this.$simpleStore.delLoader('atLeastOneResourceGraphLoaded');
            }
        },

        isResourceValidDateRange(resourceType) {
            const range = this.resourceCustomDateRanges[resourceType];
            if (!range.dates.start || !range.dates.end || !range.times.start || !range.times.end) {
                return false;
            }

            const startDateTime = new Date(`${range.dates.start}T${range.times.start}:00`);
            const endDateTime = new Date(`${range.dates.end}T${range.times.end}:00`);

            const minDateStr = this.resourceGraphs[resourceType][0]?.earliestDateSplitted || '2020-01-01';
            const todayDateStr = new Date().toISOString().substr(0, 10);

            return !isNaN(startDateTime.getTime()) && !isNaN(endDateTime.getTime()) && startDateTime <= endDateTime && range.dates.start >= minDateStr && range.dates.end <= todayDateStr;
        },

        async applyResourceCustomDateRange(resourceType) {
            if (!this.isResourceValidDateRange(resourceType)) {
                return;
            }

            const range = this.resourceCustomDateRanges[resourceType];
            const fromDateTime = `${range.dates.start}T${range.times.start}:00Z`;
            const toDateTime = `${range.dates.end}T${range.times.end}:00Z`;

            if (resourceType === 'cpu') {
                await this.getCpuGraphs(null, {
                    from: fromDateTime,
                    to: toDateTime
                });
            } else if (resourceType === 'memory') {
                await this.getMemoryGraphs(null, {
                    from: fromDateTime,
                    to: toDateTime
                });
            } else if (resourceType === 'diskio') {
                await this.getDiskIoGraphs(null, {
                    from: fromDateTime,
                    to: toDateTime
                });
            }

            this.closeCustomDateDropdown();
        },
    }
}