window.highlightTest = [];

window._$ = $;
_$.getLib(config.webRoot + 'js/jquery/lib.js', {root: false}, function(){
    window.$ = _$;
    $.getLib(config.webRoot + 'js/plotly/min.js', {root: false}, function() {
        $.getLib(config.webRoot + 'js/range/min.js', {root: false}, function(){
            
            Plotly.setPlotConfig({locale: clientLang});
            Plotly.setPlotConfig({displaylogo: false, responsive: true});
            if(clientLang != 'en')
            {
                $.getLib(config.webRoot + 'js/plotly/' + clientLang + '.js', {root: false});
            }

            if(window.plotQueue?.length)
            {
                window.plotQueue.forEach(function(create) {
                    create();
                });
            }
        });
    });
});

window.updateAnalysisMethod = function()
{
    loadCurrentPage('#mainContent #mainContentCell');
}

/**
 * Highlight test points.
 *
 * @param  object    $btn
 * @access public
 * @return void
 */
function highlightTestPoints($btn)
{
    let points = $btn.data('points');
    points = points.split(';');
    window.highlightTest = points;
    $btn.addClass('highlight-active');
    updateDTable();
}

$(document).off('click', '.highlight-points').on('click', '.highlight-points', function(e)
{
    const $btn     = $(e.target).hasClass('highlight-points') ? $(e.target) : $(e.target).closest('.highlight-points');
    const isActive = $btn.hasClass('highlight-active');

    window.highlightTest = [];
    $('.highlight-points').removeClass('highlight-active');
    updateDTable();

    if(!isActive) highlightTestPoints($btn);
});

function removeHightlightTest()
{
    window.highlightTest = [];
    $('.highlight-points').removeClass('highlight-active');
    updateDTable();
}

window.initDataframe = function()
{
    const $panel        = $('.analysis-methods .panel');
    const $highlightBtn = $panel.find('.highlight-points').first();
    if($highlightBtn.length) highlightTestPoints($highlightBtn);
}

function updateDTable()
{
    const dtable = zui.DTable.query($('.dtable'));
    dtable.render();

    if(window.highlightTest?.length > 0)
    {
        const [col, row] = window.highlightTest[0].split(',');
        dtable.$.scrollTo({row: row, col: col});
    }
}

/** Request rename analysis */
function requestRenameAnaysis(id, event)
{
    $.zui.modalTrigger.show(
    {
        type:  'iframe',
        url:   createLink('analysis', 'rename', 'analysisID=' + id),
        width: 650
    });
    event.preventDefault();
}

/** Open analysis in tabs */
function openAnalysis(analysisID, name)
{
    var tabs = $('#tabs').data('zui.tabs');
    tabs.open({title: name, id: analysisID, ajax: createLink('project', 'ajaxgetanalysis', 'analysisID=' + analysisID), forbidClose: true})
    $.getJSON(createLink('analysis', 'ajaxGetAnalysisList', 'analysisID=' + analysisID), function(data)
    {
        window.analysisList = data.data;
        initTabs();
    });
}


/* Calculate navs width on window resize */
function calculateNavsWidth($nav)
{
    var width = $nav.parent().width() - 40;
    $nav.toggleClass('is-compact', (width / $nav.children().length) < 120);
    return width;
}

/**
 * use window.dispatch to trigger resize func to resize plotly
 *
 */

function resizePlotly()
{
    var myEvent = new Event('resize');
    window.dispatchEvent(myEvent);
}

/**
 * Set a interval to wait img created.
 *
 * @param  function $callback
 * @param  int      $chartCount
 * @access public
 * @return void
 */
function waitImg(callback, chartCount)
{
    var count = 1;
    var timer = setInterval(function()
    {
        count ++;
        if($('img.plotly_img').length >= chartCount || count > 30)
        {
            callback();
            clearInterval(timer);
        }
    }, 100);
}

function noPermissionMsg(){
    return zui.Messager.show({
        placement: 'top',
        content: '没有权限使用粘贴板',
        type: 'danger',
    });
}

window.clipboardPermission = null;
async function getClipboardPermission(callback){
    if(!window.clipboardPermission){
        const {state} = await navigator.permissions.query({name: 'clipboard-read'});
        window.clipboardPermission = state;
    }
    if(window.clipboardPermission === 'denied') return noPermissionMsg();
    if(typeof callback === 'function') callback();
}

window.dtableContextMenu = function(e, info)
{
    var copy     = {text: lang.copy, order: 1, onClick: () => {getClipboardPermission(() => {this.copySelections();})}};
    var copyCol  = {text: lang.copyCol, order: 2, onClick: () => {getClipboardPermission(() => {this.copySelectedCols();})}};
    var cut      = {text: lang.cut, order: 3, onClick: () => {getClipboardPermission(() => {this.cutSelections();})}};
    var clear    = {text: lang.clear, order: 4, onClick: () => {this.deleteSelections()}};
    var clearCol = {text: lang.clear, order: 5, onClick: () => {this.clearSelectedCols()}};


    var pasteCol       = {text: lang.paste, order: 6, onClick: () => {getClipboardPermission(() => {this.pasteToSelectedCol();})}};
    var pasteSelection = {text: lang.paste, order: 6, onClick: () => {getClipboardPermission(() => {this.pasteToSelection();})}};

    var upCells   = {text: lang.upCells, order: 1, onClick: () => {
        var cells = this.getSelectedCells();
        if(!cells.length) return;
        const {row: firstRowIndex, col: firstColIndex} = cells[0];
        const {row: lastRowIndex, col: lastColIndex}   = cells[cells.length - 1];
        const rowsCount = this.layout.rows.length;
        const datasource = [];
    
        for(let i = 0; i< rowsCount; i++)
        {
            var rowValues = [];
            for(let j = firstColIndex; j <= lastColIndex; j++)
            {
                const col = this.layout.cols.list[j];
                const value = this.getCellDraftValue(i, col);
                rowValues.push(value === undefined ? '' : value);
            }
    
            datasource.push(rowValues.join('\t'));
        }
    
        var data = datasource.filter((col, index) => index >= (lastRowIndex + 1)).concat('').join('\n');
        this.pasteCells(cells[0], {data, select: false});
    }}

    var deleteCol = {text: lang.deleteCol, order: 2, onClick: () => {this.deleteSelectedCols()}};
    var deleteRow = {text: lang.deleteRow, order: 3, onClick: () => {this.deleteSelectedRows()}};

    var deleteColByCell = {text: lang.deleteCol, order: 10, onClick: () => {
        var cells = this.getSelectedCells();
        if(!cells.length) return;
        var col = this.layout.cols.list[cells[0].col];
        this.deleteCols(col);
    }};
    var deleteRowByCell = {text: lang.deleteRow, order: 10, onClick: () => {
        var cells = this.getSelectedCells();
        if(!cells.length) return;
        var row = this.getRowInfoByIndex(cells[0].row);
        this.deleteRows(row);
    }};

    if(info.rowID === 'HEADER') return [copyCol, cut, clearCol, deleteCol, pasteCol];
    if(info.colName === 'INDEX') return [copy, pasteSelection, cut, clear, deleteRow];
    return [
        copy, cut, clear, pasteSelection,
        {text: lang.delete, order: 5, items: [upCells, deleteColByCell, deleteRowByCell], onClick: () => false}
    ];
}

window.onColResize = function(e, info)
{
    //$.post($.createLink('analysis', 'ajaxSetColumnWidth', 'analysisID=' + analysisID), {col: colName.replace('C', ''), width: width});
}

window.onReadClipboardFail = function(e, info)
{
    bootbox.alert(clipboardFailTip);
}

window.onRenderHeaderCell = function(result, info)
{
    if(info.col.name === 'INDEX' && info.row.id === 'HEADER') return [''];
    if(result[0] === info.col.name || (result[0] && typeof result[0] === 'object' && result[0].children === info.col.name)) result[0] = '';
    if(info.col.name !== 'INDEX')
    {
        result.unshift({html: '<div class="dataframe-col-name">' + info.col.name + '</div>'});
    }
    return result;
}

window.onRenderCell = function(result, info)
{
    const {row, col} = info;
    if(col.name !== 'INDEX')
    {
        const rowIndex = row.index + 1;
        const colIndex = col.index - 1;
        var className  = 'dtable-cell-content';

        if(window.highlightTest?.includes(`${colIndex},${rowIndex}`)) className += ' highlight-test';
        if(result[0]?.attrs)result[0].attrs.class = className;
    }

    return result;
}

/** Handle dataframe change and push changes to server */
function postDataframe(changes, skipApplyChange)
{
    var data = {};
    var colNames = {};
    $.each(changes, function(rowID, rowData)
    {
        if(rowID === 'HEADER')
        {
            return $.each(rowData, function(colName, colTitle)
            {
                colNames['col' + (colName.replace('C', '') - 1)] = colTitle;
            });
        }
        $.each(rowData, function(colName, value)
        {
            if(value === undefined || value === null) value = '';

            var colIndex = colName.replace('C', '');
            var colValues = data[colIndex];
            if(!colValues)
            {
                colValues = {};
                data[colIndex] = colValues;
            }
            colValues[rowID] = value;
        });
    });
    changes = $.extend(true, {}, changes);
    $.post($.createLink('perfanalysis', 'ajaxUpdateDataframe', 'analysisID=' + analysisID), {data: JSON.stringify(data), colNames: JSON.stringify(colNames)}, (data) =>
    {
        if(!skipApplyChange && data && data.result === 'success')
        {
            this.applyDraft(changes);
            this.appendRows(1, {autoScroll: false, skipUpdate: false, select: false});
        }
    }, 'json');
}

window.handleDataframeChange = function(changes, allChanges)
{
    console.log(changes, allChanges);
    postDataframe.call(this, allChanges);
}

window.handleHistoryApplied = function(changes)
{
    console.log(changes);
    postDataframe.call(this, changes, true);
}

$(document).on('mouseenter', '.analysis-actions-btn', function()
{
    $(this).find('.dropdown-btn').addClass('opacity-100');
});

$(document).on('mouseleave', '.analysis-actions-btn', function()
{
    $(this).find('.dropdown-btn').removeClass('opacity-100');
});

$(document).on('mouseenter', '.menu-analysis-actions', function()
{
    const classList = $(this).attr('class');
    const matches   = classList.match(/analysis_(\d+)/);

    if(matches)
    {
        const analysisID = matches[1];
        $(`.analysis-actions-btn[data-id="${analysisID}"]`).find('.dropdown-btn').addClass('opacity-100');
    }
});

$(document).on('mouseleave', '.menu-analysis-actions', function()
{
    $('.analysis-actions-btn .dropdown-btn').removeClass('opacity-100');
});

window.onCopyMethod = async function(event)
{
    const methodID = $(event).closest('.panel').data('methodid');
    let chartCount = 0;
    const $tab     = $(event).closest('#mainContentCell');
    const $panel   = $(event).closest('.panel');

    setTimeout(function()
    {
        const $e        = $(event).parent();
        const $original = $e.clone();
        $e.replaceWith($original);
    }, 500);

    let i = 0;
    const data = await $.getJSON($.createLink('perfanalysis', 'ajaxGetMethodResult', 'methodID=' + methodID));
    if(data.result == 'success')
    {
        for(let result of data.data.results) if(result.type == 'chart') chartCount ++;
        for(let j = 1; j <= chartCount + 1; j ++) $tab.append('<div class="hidden" id="plotly_div' + j + '"></div>');

        for(let result of data.data.results)
        {
            if(result.type == 'chart')
            {
                $panel.find('.analysis-method-result,#collapse' + methodID + ',#analysisMethod' + methodID).each(async function()
                {
                    if(result.id == $(this).data('id'))
                    {
                        i ++;
                        const gd = await Plotly.newPlot('plotly_div' + i, eval(result.data.data), eval(result.data.layout));
                        const res = await Plotly.toImage(gd,{height:500,width:1000});
                        $(this).find('.plot-container').addClass('hidden');
                        $(this).find('.plot-container').after('<img class="plotly_img" src=' + res + '></img>');
                    }
                });
            }
        }
    }
    for(let j = 1; j <= chartCount + 1; j ++) $('#plotly_div' + j).remove();

    await new Promise(resolve => setTimeout(resolve, 100));

    if(window.getSelection)
    {
        window.getSelection().removeAllRanges();
    }
    else if(document.selection)
    {
        document.selection.empty();
    }

    const range = document.createRange();
    const node = $panel[0];
    
    if(!node) return false;

    try {
        range.selectNodeContents(node);
        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);

        if(chartCount)
        {
            waitImg(function()
            {
                try {
                    const selection = window.getSelection();
                    if(selection.rangeCount === 0)
                    {
                        selection.removeAllRanges();
                        selection.addRange(range);
                    }

                    document.execCommand('copy');
                    selection.removeAllRanges();
                    $('.plotly_img').remove();
                    $('.plot-container').removeClass('hidden');
                    zui.Messager.show({content: copySuccess, type: 'success'});
                } catch (err) {
                    zui.Messager.show({content: copyFailed, type: 'danger'});
                }
            }, chartCount);
        }
        else
        {
            try {
                document.execCommand('copy');
                window.getSelection().removeAllRanges();
                zui.Messager.show({content: copySuccess, type: 'success'});
            } catch (err){
                zui.Messager.show({content: copyFailed, type: 'danger'});
            }
        }
    } catch (err) {
        zui.Messager.show({content: copyFailed, type: 'danger'});
    }
    return false;
};

window.toggleCollapse = function(event)
{
    $(event).closest('.panel').find('.panel-body').toggleClass('hidden');
    $(event).toggleClass('rotate-180');
}

window.refreshMethod = function(event)
{
    const methodID = $(event).closest('.panel').data('methodid');
    $.getJSON($.createLink('perfanalysis', 'refresh', 'methodID=' + methodID), function(data)
    {
        if(data && data.result === 'success')
        {
            loadPage($.createLink('perfproject', 'analysis', 'analysisID=' + analysisID));
            setTimeout(function()
            {
                if(data.message) zui.Messager.show({content: data.message, type: 'success'});
                let $highlightBtn = $(event).closest('.panel').find('.highlight-points');
                if($highlightBtn.length) highlightTestPoints($highlightBtn);
            }, 1000);
        }
        else
        {
            if(data.message) zui.Messager.show({content: data.message, type: 'danger'});
        }
    });
    return false;
}

window.refreshAll = function()
{
    const analysisID = $('.analysis-methods').data('analysisID');
    $.getJSON($.createLink('perfanalysis', 'refreshAll', 'analysisID=' + analysisID), function(data)
    {
        if(data && data.result === 'success')
        {
            if(data.methodIDList) loadPage($.createLink('perfproject', 'analysis', 'analysisID=' + analysisID));
            removeHightlightTest();
            if(data.message) zui.Messager.show({content: data.message, type: 'success'});
        }
        else
        {
            if(data.message) zui.Messager.show({content: data.message, type: 'danger', close: true, icon: 'exclamation-sign'});
        }
    });
}

window.calculateHeight = function()
{
    const height = $(document).height() - $('#header').height() - $('#mainMenu').height() - 105;
    return height;
}
