<?php

include_once '.autoload.php';

use Axioma\Utils as utils;

$errors = array();
$warnings = array();
$info = array();
$error = '';

$app = new Axioma\Server\App();

$user_list = $app->getLicenseHistory($error);
if (!empty($error)) {
    $errors[] = $error;
}

?>

<div class="historyDiv">
    <table id="historyTbl" class="display compact">
        <thead>
            <tr>
                <th>
                    <?php echo _('Имя'); ?>
                </th>
                <th>
                    <?php echo _('IP адрес'); ?>
                </th>
                <th>
                    <?php echo _('id сессии'); ?>
                </th>
                <th>
                    <?php echo _('Версия ПО'); ?>
                </th>
                <th>
                    <?php echo _('Активна'); ?>
                </th>
                <th>
                    <?php echo _('Начало сеанса'); ?>
                </th>
                <th>
                    <?php echo _('Завершение сеанса'); ?>
                </th>
                <th>
                    <?php echo _('Длительность сеанса'); ?>
                </th>
                <th>
                    <?php echo _('Действует до'); ?>
                </th>
            </tr>
        </thead>
    </table>
</div>

<?php utils::showMessageBlocks($errors, $warnings, $info, 'historyDiv'); ?>

<script>
    window.onload = function(event) {
        if (!document.getElementById('content')) {
            window.location = 'index.php?page=history';
        }
    };
    $(document).ready(function () {
        var table_data = <?php echo json_encode($user_list); ?>;
        var table = $('#historyTbl').DataTable({
            data: table_data,
            columns: [
                { data: "username" },
                { data: "ip" },
                { data: "sid" },
                {
                    data: "version",
                    searchBuilder: { orthogonal: 'display' },
                    searchBuilderType: 'version_str'
                },
                {
                    data: "active",
                    render: function (data, type, row, meta) {
                        if (type === 'display') {
                            return data ? '&#x2713;' : '&#x2717;';
                        }
                        return data;
                    },
                    searchBuilder: { orthogonal: 'filter' },
                    searchBuilderType: 'bool'
                },
                { data: "acquired" },
                { data: "released" },
                {
                    data: "duration",
                    render: function (data, type, row, meta) {
                        if (!data) {
                            return data;
                        }
                        var dt = luxon.Duration.fromMillis(Number(data) * 1000);
                        if (type === 'display') {
                            return dt.toFormat('h:mm:ss');
                        }
                        return data;
                    },
                    searchBuilder: { orthogonal: 'filter' },
                    searchBuilderType: 'timediff'
                },
                { data: "expire" }
            ],
            dom: 'l<"right"f>tip',
            paging: true,
            lengthMenu: [[5, 10, 20, 50, -1], [5, 10, 20, 50, "<?php echo _('Все'); ?>"]],
            pageLength: 20,
            pagingType: 'numbers',
            columnDefs: [
                { visible: false, targets: [1, 2, 3, 8] },
                { searchable: false, targets: [2, 3, 4, 5, 6, 7, 8] },
                {
                    targets: [5, 6, 8],
                    render: function (data, type, row, meta) {
                        if (!data) {
                            return data;
                        }
                        var dt = luxon.DateTime.fromSeconds(Number(data));
                        if (type === 'display') {
                            return dt.toLocaleString(luxon.DateTime.DATETIME_SHORT);
                        }
                        return data;
                    },
                    searchBuilder: { orthogonal: 'filter' },
                    searchBuilderType: 'timestamp'
                }
            ],
            order: [5, 'desc'],
            language: {
                url: 'js/datatables.ru.json'
            },
            select: true,
            stateSave: true,
            initComplete: function () {
                new $.fn.dataTable.Buttons(table, {
                    buttons: [
                        { extend: 'colvis', text: "<?php echo _('Выбор колонок'); ?>", className: 'historyBtn' },
                        {
                            extend: 'searchBuilder',
                            className: 'historyBtn',
                            config: {
                                conditions: {
                                    bool: {
                                        'true': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Да'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) { return +value == 1; },
                                        },
                                        'false': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Нет'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) { return +value == 0; },
                                        }
                                    },
                                    version_str: {
                                        '=': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Равно'); ?>"; },
                                            isInputValid: function (el, that) {
                                                return el[0].children('option:selected').length === 1;
                                            },
                                            init: sbInitVersionSelect,
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                return compareVersion(value, comparison[0]) === 0;
                                            }
                                        },
                                        '!=': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Не равно'); ?>"; },
                                            isInputValid: function (el, that) {
                                                return el[0].children('option:selected').length === 1;
                                            },
                                            init: sbInitVersionSelect,
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                return compareVersion(value, comparison[0]) !== 0;
                                            }
                                        },
                                        '<=': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Не выше'); ?>"; },
                                            isInputValid: function (el, that) {
                                                return el[0].val().length !== 0;
                                            },
                                            init: sbInitInput,
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {

                                                return compareVersion(value, comparison[0]) !== 1;
                                            }
                                        },
                                        '>=': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Не ниже'); ?>"; },
                                            isInputValid: function (el, that) {
                                                return el[0].val().length !== 0;
                                            },
                                            init: sbInitInput,
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                return compareVersion(value, comparison[0]) !== -1;
                                            }
                                        },
                                        'major': {
                                            conditionName: function (dt, i18n) { 
                                                return "<?php echo _('Старшая версия'); ?>"; 
                                            },
                                            isInputValid: function (el, that) {
                                                return el[0].children('option:selected').length === 1;
                                            },
                                            init: sbInitVersionMajorSelect,
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                return value && +value.split('.')[0] === +comparison[0];
                                            }
                                        },
                                        'null': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Пусто'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return value === null || value === undefined || value.length === 0;
                                            }
                                        }
                                    },
                                    timediff: {
                                        '<': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Меньше чем'); ?>"; },
                                            init: sbInitTimediff,
                                            isInputValid: function (els, that) {
                                                return els[0].val().length !== 0 &&
                                                    els[2].children('option:selected').length === 1;
                                            },
                                            inputValue: function (els) {
                                                return [els[0].val(), els[2].val()];
                                            },
                                            search: function (value, comparison, that) {
                                                var comp = +comparison[0];
                                                switch (comparison[1]) {
                                                    case 'h': comp *= 3600; break;
                                                    case 'm': comp *= 60; break;
                                                    default: break;
                                                }
                                                return +value <= comp;
                                            }
                                        },
                                        '>': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Больше чем'); ?>"; },
                                            init: sbInitTimediff,
                                            isInputValid: function (els, that) {
                                                return els[0].val().length !== 0 &&
                                                    els[2].children('option:selected').length === 1;
                                            },
                                            inputValue: function (els) {
                                                return [els[0].val(), els[2].val()];
                                            },
                                            search: function (value, comparison, that) {
                                                var comp = +comparison[0];
                                                switch (comparison[1]) {
                                                    case 'h': comp *= 3600; break;
                                                    case 'm': comp *= 60; break;
                                                    default: break;
                                                }
                                                return +value >= comp;
                                            }
                                        },
                                        'between': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Между'); ?>"; },
                                            init: sbInitTimediff2,
                                            isInputValid: function (els, that) {
                                                return els[0].val().length !== 0 &&
                                                    els[2].val().length !== 0 &&
                                                    els[4].children('option:selected').length === 1;
                                            },
                                            inputValue: function (els) {
                                                return [els[0].val(), els[2].val(), els[4].val()];
                                            },
                                            search: function (value, comparison, that) {
                                                var comp1 = +comparison[0];
                                                var comp2 = +comparison[1];
                                                switch (comparison[2]) {
                                                    case 'h': comp1 *= 3600; comp2 *= 3600; break;
                                                    case 'm': comp1 *= 60; comp2 *= 60; break;
                                                    default: break;
                                                }
                                                if (comparison[0] < comparison[1]) {
                                                    return comp1 <= +value && +value <= comp2;
                                                } else {
                                                    return comp2 <= +value && +value <= comp1;
                                                }
                                            }
                                        },
                                        'null': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Пусто'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return value === null || value === undefined || value.length === 0;
                                            }
                                        }
                                    },
                                    timestamp: {
                                        'today': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Сегодня'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return +value >= luxon.DateTime.now().startOf('day').toSeconds();
                                            }
                                        },
                                        'yesterday': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Вчера'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                let midnight = luxon.DateTime.now().startOf('day');
                                                return +value < midnight.toSeconds() &&
                                                    +value >= midnight.plus({ days: -1 }).toSeconds();
                                            }
                                        },
                                        'this-week': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Эта неделя'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return +value > luxon.DateTime.now().startOf('week').toSeconds();
                                            }
                                        },
                                        'last-week': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Прошлая неделя'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                let monday_midnight = luxon.DateTime.now().startOf('week');
                                                return +value < monday_midnight.toSeconds() &&
                                                    +value >= monday_midnight.plus({ week: -1 }).toSeconds();
                                            }
                                        },
                                        'this-month': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Этот месяц'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return +value > luxon.DateTime.now().startOf('month').toSeconds();
                                            }
                                        },
                                        'last-month': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Прошлый месяц'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                let month_midnight = luxon.DateTime.now().startOf('month');
                                                return +value < month_midnight.toSeconds() &&
                                                    +value >= month_midnight.plus({ month: -1 }).toSeconds();
                                            }
                                        },
                                        'date': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Дата'); ?>"; },
                                            init: sbInitDate,
                                            isInputValid: function (el, that) {
                                                return el[0].val().length !== 0;
                                            },
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                if (!value) {
                                                    return false;
                                                }
                                                let dt = luxon.DateTime.fromSeconds(+value);
                                                return comparison[0] == dt.toFormat('d.MM.yyyy');
                                            }
                                        },
                                        'after': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('После'); ?>"; },
                                            init: sbInitDateTime,
                                            isInputValid: function (el, that) {
                                                return el[0].val().length !== 0;
                                            },
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                if (!value) {
                                                    return false;
                                                }
                                                let dt = luxon.DateTime.fromSeconds(+value);
                                                let cmp = luxon.DateTime.fromFormat(comparison[0], 'd.MM.yyyy HH:mm');
                                                return dt >= cmp;
                                            }
                                        },
                                        'before': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('До'); ?>"; },
                                            init: sbInitDateTime,
                                            isInputValid: function (el, that) {
                                                return el[0].val().length !== 0;
                                            },
                                            inputValue: function (el) { return [el[0].val()]; },
                                            search: function (value, comparison, that) {
                                                if (!value) {
                                                    return false;
                                                }
                                                let dt = luxon.DateTime.fromSeconds(+value);
                                                let cmp = luxon.DateTime.fromFormat(comparison[0], 'd.MM.yyyy HH:mm');
                                                return dt <= cmp;
                                            }
                                        },
                                        'between': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Между'); ?>"; },
                                            init: sbInitDateTime2,
                                            isInputValid: function (el, that) {
                                                return el[0].val().length !== 0 && el[2].val().length !== 0;
                                            },
                                            inputValue: function (el) { return [el[0].val(),el[2].val()]; },
                                            search: function (value, comparison, that) {
                                                if (!value) {
                                                    return false;
                                                }
                                                let dt = luxon.DateTime.fromSeconds(+value);
                                                let cmp1 = luxon.DateTime.fromFormat(comparison[0], 'd.MM.yyyy HH:mm');
                                                let cmp2 = luxon.DateTime.fromFormat(comparison[1], 'd.MM.yyyy HH:mm');
                                                if (cmp1 < cmp2) {
                                                    return dt >= cmp1 && dt <= cmp2;
                                                }
                                                return dt <= cmp1 && dt >= cmp2;
                                            }
                                        },
                                        'null': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Пусто'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return value === null || value === undefined || value.length === 0;
                                            }
                                        },
                                        '!null': {
                                            conditionName: function (dt, i18n) { return "<?php echo _('Не пусто'); ?>"; },
                                            isInputValid: function () { return true; },
                                            init: function () { return; },
                                            inputValue: function () { return []; },
                                            search: function (value, comparison, that) {
                                                return value !== null && value !== undefined && value.length > 0;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    ]
                });
                this.api().buttons(0, null).container().appendTo(table.table().container());
                new $.fn.dataTable.Buttons(table, {
                    buttons: [
                        { extend: 'copy', exportOptions: { columns: ':visible' }, className: 'historyBtn' },
                        {
                            extend: 'collection',
                            text: "<?php echo _('Экспорт данных...'); ?>",
                            autoClose: true,
                            buttons: [
                                'csv',
                                'excel',
                                { extend: 'pdf', exportOptions: { columns: ':visible' } }
                            ],
                            className: 'historyBtn'
                        },
                        {
                            extend: 'print',
                            exportOptions: { columns: ':visible' },
                            className: 'historyBtn'
                        }
                    ]
                });
                this.api().buttons(1, null).container().appendTo(table.table().container());
                new $.fn.dataTable.Buttons(table, {
                    buttons: [
                        {
                            text: "<?php echo _('Обновить данные'); ?>",
                            action: function (e, dt, node, config) {
                                $('#content').load('history.php');
                            },
                            className: 'historyBtn'
                        },
                        {
                            text: "<?php echo _('Вернуться на главную'); ?>",
                            action: function (e, dt, node, config) {
                                $('#content').load('status.php');
                            },
                            className: 'historyBtn'
                        }
                    ]
                });
                this.api().buttons(2, null).container().appendTo(table.table().container());
            }
        });
    });

    function sbInitInput(that, fn, preDefined = null) {
        let el = $('<input/>').on('input', function () { fn(that, this) });
        if (preDefined !== null && preDefined[0]) {
            el.val(preDefined[0]);
        }
        return el;
    };
    function sbInitTimediff(that, fn, preDefined = null) {
        let els = [
            $('<input/>').on('input', function () { fn(that, this) }),
            $('<span>').html('&nbsp;'),
            $('<select/>').on('change', function () { fn(that, this) })
                .append(that.dom.valueTitle)
                .append($('<option>', { value: 'h', text: "<?php echo _('ч'); ?>" }))
                .append($('<option>', { value: 'm', text: "<?php echo _('мин'); ?>" }))
                .append($('<option>', { value: 's', text: "<?php echo _('сек'); ?>" }))
        ];
        if (preDefined !== null && preDefined[0]) {
            els[0].val(preDefined[0]);
        }
        if (preDefined !== null && preDefined[1]) {
            els[2].val(preDefined[1]);
        }
        return els;
    };
    function sbInitTimediff2(that, fn, preDefined = null) {
        let els = [
            $('<input/>').on('input', function () { fn(that, this) }),
            $('<span>').html("<?php echo _(' и '); ?>"),
            $('<input/>').on('input', function () { fn(that, this) }),
            $('<span>').html('&nbsp;'),
            $('<select/>').on('change', function () { fn(that, this) })
                .append(that.dom.valueTitle)
                .append($('<option>', { value: 'h', text: "<?php echo _('ч'); ?>" }))
                .append($('<option>', { value: 'm', text: "<?php echo _('мин'); ?>" }))
                .append($('<option>', { value: 's', text: "<?php echo _('сек'); ?>" }))
        ];
        if (preDefined !== null) {
            if (preDefined[0]) els[0].val(preDefined[0]);
            if (preDefined[1]) els[2].val(preDefined[1]);
            if (preDefined[2]) els[4].val(preDefined[2]);
        }
        return els;
    };
    function compareVersion(a, b) {
        var as = a.split('.');
        var bs = b.split('.');
        for (let idx = 0; idx < as.length && idx < bs.length; idx++) {
            if (as[idx] < bs[idx]) {
                return -1;
            }
            else if (as[idx] > bs[idx]) {
                return 1;
            }
        }
        return (as.length > bs.length) ? 1 : (as.length < bs.length ? -1 : 0);
    };
    function sbInitVersionSelect(that, fn, preDefined = null) {
        let column = that.dom.data.children('option:selected').val();
        let indexArray = that.s.dt.rows().indexes().toArray();
        let settings = that.s.dt.settings()[0];
        that.dom.valueTitle.prop('selected', true);

        let el = $('<select/>').append(that.dom.valueTitle).on('change', function () { fn(that, this); });
        let added = [];
        let options = [];
        for (let index of indexArray) {
            let filter = settings.oApi._fnGetCellData(
                settings, index, column, typeof that.c.orthogonal === 'string' ?
                that.c.orthogonal :
                that.c.orthogonal.search
            );
            let value = {
                filter: typeof filter === 'string' ?
                    filter.replace(/[\r\n\u2028]/g, ' ') : // Need to replace certain characters to match search values
                    filter,
                index,
                text: settings.oApi._fnGetCellData(
                    settings,
                    index,
                    column,
                    typeof that.c.orthogonal === 'string' ?
                        that.c.orthogonal :
                        that.c.orthogonal.display
                )
            };
            let addOption = function (filt, text) {
                if (that.s.type.includes('html') && filt !== null && typeof filt === 'string') {
                    filt.replace(/(<([^>]+)>)/ig, '');
                }

                let opt = $('<option>', {value: filt})
                    .html(typeof text === 'string' ? text.replace(/(<([^>]+)>)/ig, '') : text);
                let val = opt.val();

                if (added.indexOf(val) === -1) {
                    added.push(val);
                    options.push(opt);
                    if (preDefined !== null && opt.val() === preDefined[0]) {
                        opt.prop('selected', true);
                        that.dom.valueTitle.removeProp('selected');
                    }
                }
            };
            addOption(value.filter, value.text);
        }
        options.sort(compareVersion);
        for (let opt of options) {
            el.append(opt);
        }

        return el;
    };
    function sbInitVersionMajorSelect(that, fn, preDefined = null) {
        let column = that.dom.data.children('option:selected').val();
        let indexArray = that.s.dt.rows().indexes().toArray();
        let settings = that.s.dt.settings()[0];
        that.dom.valueTitle.prop('selected', true);

        let el = $('<select/>').append(that.dom.valueTitle).on('change', function () { fn(that, this); });
        let added = [];
        let options = [];
        for (let index of indexArray) {
            let filter = settings.oApi._fnGetCellData(
                settings, index, column, typeof that.c.orthogonal === 'string' ?
                that.c.orthogonal :
                that.c.orthogonal.display
            );
            let value = filter ? filter.split('.')[0] : filter;
            let addOption = function (val) {
                if (val === null) {
                    return;
                }
                let opt = $('<option>', {value: val}).html(val);
                if (added.indexOf(val) === -1) {
                    added.push(val);
                    options.push(opt);
                    if (preDefined !== null && opt.val() === preDefined[0]) {
                        opt.prop('selected', true);
                        that.dom.valueTitle.removeProp('selected');
                    }
                }
            };
            addOption(value);
        }
        options.sort(compareVersion);
        for (let opt of options) {
            el.append(opt);
        }

        return el;
    };
    function sbInitDate(that, fn, preDefined = null) {
        let el = $('<input/>')
            .dtDateTime({
                attachTo: 'input',
                format: 'dd.MM.yyyy'
            })
            .on('change', function () { fn(that, this); })
            .on('input', function () { fn(that, this); });
        if (preDefined !== null) {
            el.val(preDefined[0]);
        }
        return el;
    };
    function sbInitDateTime(that, fn, preDefined = null) {
        let el = $('<input/>')
            .dtDateTime({
                attachTo: 'input',
                format: 'dd.MM.yyyy HH:mm'
            })
            .on('change', function () { fn(that, this); })
            .on('input', function () { fn(that, this); });
        if (preDefined !== null) {
            el.val(preDefined[0]);
        }
        return el;
    };
    function sbInitDateTime2(that, fn, preDefined = null) {
        let el = [$('<input/>')
            .dtDateTime({
                attachTo: 'input',
                format: 'dd.MM.yyyy HH:mm'
            })
            .on('change', function () { fn(that, this); })
            .on('input', function () { fn(that, this); }),
            $('<span>').html('&nbsp;'),
            $('<input/>')
            .dtDateTime({
                attachTo: 'input',
                format: 'dd.MM.yyyy HH:mm'
            })
            .on('change', function () { fn(that, this); })
            .on('input', function () { fn(that, this); })
        ]
        if (preDefined !== null && preDefined[0]) {
            el[0].val(preDefined[0]);
        }
        if (preDefined !== null && preDefined[1]) {
            el[2].val(preDefined[1]);
        }
        return el;
    };
</script>
