

ej.base.registerLicense('ORg4AjUWIQA/Gnt2XFhhQlJHfV5AQmBIYVp/TGpJfl96cVxMZVVBJAtUQF1hTH5VdkxhWnpWcHZcTmhfWkZ/')
ej.spreadsheet.Spreadsheet.Inject(ej.spreadsheet.ExcelExport);
var studio = {_context:''}
studio.defaults = {
    'duckdb':'SELECT * \nFROM INFORMATION_SCHEMA.TABLES',
    'sqlite':'SELECT * \nFROM sqlite_master',
    'sqlite3':'SELECT * \nFROM sqlite_master',
    'bigquery':'SELECT * \nFROM <dataset>.INFORMATION_SCHEMA.COLUMNS \nLIMIT 10',
    'postgresql':'SELECT *\nFROM INFORMATION_SCHEMA.COLUMNS LIMIT 10',
    'iceberg':'SHOW TABLES',
    'mysql':'SELECT * \nFROM INFORMATION_SCHEMA.COLUMNS LIMIT 10',
    'mariadb':'SHOW TABLES','files':'{"query":"index > -1"}'
}
studio.init = function (_context){
    studio._context = _context
}
studio.dbe = {}
// studio.dbe.get = function (){
//     var uri = [studio._context,'api/dbe/get']
//     uri = uri.join('/')
//     var http = HttpClient.instance()
//     http.get(uri,function(x){

//     })


// }

studio.dbe.providers = function (_render){
    var uri = [studio._context,'api/transport/providers']
    uri = uri.join('/')
    var http = HttpClient.instance()
    http.get(uri,function(x){
        var _data = JSON.parse(x.responseText)
        if (_render){
            _render(_data)
        }

    })
}


// studio.dbe.apply = function (label,_query){
//     var uri = [studio._context,'api/transport/apply']
//     uri = uri.join('/')
    
//     var http = HttpClient.instance()
//     _data = {'label':label,'query':_query}
//     http.setHeader('Content-Type','application/json')
//     http.setData (JSON.stringify(_data))
//     http.get(uri,function(x){
//         if(x.status == 200 && x.readyState == 4){
//             _r = JSON.stringify(x.responseText)
//         }else{
//             alert(' error round '+x.responseText)
//         }
//     })

// }
function triggerDownload(blob, filename) {
    const url = URL.createObjectURL(blob); // create a temporary URL
    const a = document.createElement("a");
    a.href = url;
    a.download = filename; // suggest a filename
    document.body.appendChild(a); // Firefox needs it in DOM
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url); // cleanup
}
studio.grid = function (){
    this.columns = function (_data){
        var _columns = []
        if(_data.columns){
            _data.columns.forEach(_name=>{
                _columns.push({title:_name})
            })
        }
        return _columns
    }
    this.dataTable = function (_id,_data){
       $(_id).html('<table class="display"></table>')
       $(_id.replace(/output/,'status')).hide()
       
        _id = _id + ' table'
        var _columns = []
        if (_data.columns ){
            _data.columns.forEach(_name=>{
                _columns.push({title:_name})
            })
            var _args = {'data':_data.data,'columns':_columns}
            // _args.layout = {topStart:{}}
            _args.buttons = ['excel','pdf']
                
        }else{
            _data = {'data':[],columns:[]}
        }
        _args.dom = 'rtip'
        _args.scrollCollapse = true
        _args.scrollY = '400px'   
        var _grid = new DataTable(_id,_args)     
        return _grid;
    }
    this.gridjs = function (_id, _data){
        $(_id.replace(/output/,'status')).hide()
        var grid = new gridjs.Grid({
            // columns:_data.columns, 
            data:_data.data , //_data.data,
            columns:_data.columns,
            fixedHeader:true, resizable:true,
            search:false,
            
            style:{
                th:{height:'20px',overflow:'hidden','text-overflow':'ellipsis'},
                td :{height:'20px',padding:'4px',overflow:'hidden','text-overflow':'ellipsis'}, 
                table:{overflow:'hidden','text-overflow':'ellipsis','white-space':'nowrap',border:'1px solid transparent'}
            },
            sort:true,
            pagination:true,
            height:'405px'})
        if ($(_id).is(':empty')){
            grid.render($(_id)[0])
        }
            grid.forceRender($(_id)[0])        
    }
    this.spreadsheet = function (_id, _data){
        var _div = $(_id)[0]
        var _columns = this.columns(_data)
       var rows = []
        _data.data.forEach(row=>{
            var _record = {} //-- formatted appropriately
            row.forEach((value,index)=>{
                _col = _data.columns[index].name
                _record[_col] = value
            })
            rows.push(_record)
        })
                
        var _spreadsheet = jspreadsheet(_div, {
            tabs:true,toolbar:false,
            style:['text-overflow: ellipsis; white-space: nowrap;'],
            worksheets: [{
                media:[{type:'chart',options:{}}],
                data: _data.data,
                minDimensions:[20,15],
                tableOverflow:true,
                tableHeight: '400px',
                tableWidth:$(_id).width(),//minSpareCols:'auto',
                columns:_columns,
                workbookname: _id
            }]
        });
        _div.spreadsheet = _spreadsheet
        

        

    }

    this.syncfusion = function(_id,_data){
        
        var rows = []
        
        _data.data.forEach(row=>{
            var _record = {} //-- formatted appropriately
            row.forEach((value,index)=>{
                _col = _data.columns[index]
                _record[_col] = value
            })
            rows.push(_record)
        })

        var spreadsheet = new ej.spreadsheet.Spreadsheet();
        _sheet_name = _id.trim().replace(/[#,.]/g,'').replace(/ /g,'-').trim()
        spreadsheet.sheets = [
            {name:_sheet_name,
                ranges:[{dataSource:rows}],
            
            }
        ]
        if( $(_id)[0].spreadsheet ){
            book = $(_id)[0].spreadsheet ;
            book.sheets.forEach((sheet)=>{
                if(sheet.name != _sheet_name){
                    
                    spreadsheet.sheets.push(sheet)
                }
            })
            
        }
        
        // spreadsheet.openUrl='/api/io/open'
        // spreadsheet.openSettings = {chunkSize:1024}
        // spreadsheet.saveUrl = 'https://services.syncfusion.com/js/production/api/spreadsheet/save'
        // spreadsheet.created = function (){}
        // spreadsheet.sheets = [
        //     {name:_id.replace(/[#,.]/g,' '),
        //         ranges:[{dataSource:rows}],
               
        //     }
        // ]
        
        spreadsheet.saveUrl = studio._context+'api/io/write'
        
        spreadsheet.appendTo(_id)
        $(_id)[0].spreadsheet = spreadsheet
        // console.log([' **** ',(_id+' .e-input-group')])
        // $(_id+' .e-input-group').remove()
        
        spreadsheet.refresh()
        spreadsheet.hideFileMenuItems(["File"], true);
    }
    
}
studio.frame = function (_args){
    this._args = _args
    //
    // Initializing by having an input and ouput pane
    // Load the template from disk
    this.init = function (){

    }

    //
    // Render the template
    this.read = function(_args,_query,_compute){
        var _label = _args.label
        var uri = [studio._context,'api/transport/apply']
        uri = uri.join('/')
        if (_args.AI && sessionStorage.AI !="0"){
            uri = uri.replace(/transport/g,'agent')
        }
        
        // var _compute = this.compute 
        // $('.'+_label+' .output').html('<i class="fa-solid fa-cog fa-spin"></i> Please wait ...')
        var http = HttpClient.instance()
        
        _data = {'label':_label,'query':_query}
        http.setHeader('Content-Type','application/json')
        http.setData (JSON.stringify(_data))

        http.post(uri,function(x){
            var _id = `.${_args.label} .control .apply`
            
            $(_id).empty()
            $(_id).append($('<i class="fa-solid fa-play"></i>'))
            if(x.status == 200 && x.readyState == 4){
                _r = JSON.parse(x.responseText)
                // sessionStorage._data = x.responseText
                if (_r.query == null){
                _compute(_label,_r)
                }else{
                    _compute(_label,_r.data)
                    var _id = '.code.'+_args.label.trim()
                    // $(_id).val('-- '+$(_id).val().replace(/\n/g,'-- ') + '\n'+_r['query'])
                    $(_id).val(_r['query'])
                }
                sessionStorage[_label] = _query

            }else{
                const parser = new DOMParser();
                const doc = parser.parseFromString(x.responseText, 'text/html');
                _message = $(doc.querySelector('title')).text().replace(/\/\/ Werkzeug Debugger/g,'').trim()
                
                sessionStorage.error_mesage = _message
                dialog.show({uri:'www/html/error.html',title:'Error Found',context:studio._context})
            }
        })

    }
    this.open = function (_id,file){
        var http = HttpClient.instance()
        _uri = 'api/io/read'
        var form = new FormData()
        form.append('file',file)
        http.setData(form)
        var _index = $(_id)[0].spreadsheet.sheets.length 
        // _name = file.name
        
        // $(_id)[0].spreadsheet.insertSheet([{name:_name,_index:1}],0)
        // console.log([_index, $(_id)[0].spreadsheet.sheets.length])
        // $(_id)[0].spreadsheet.sheets[_index].name  = `sheet {_index}`
        http.post(_uri,function(x){
            if(x.status == 200 && x.readyState == 4){
                var _data = JSON.parse(x.responseText)
                _data.Workbook.sheets.forEach(sheet=>{
                    sheet.name = file.name
                    sheet.index=_index
                    $(_id)[0].spreadsheet.insertSheet([sheet],0)
                })
                
               
            }else{
                //@TODO:
                // handle the error in a graceful way
            }
        })
    }  
    this.show = function (){
        var _label = this._args.label
        $('.studio').each(_index=>{
            var _bench = $('.studio')[_index]
            if (_bench.className.match(_label) == null){
                $(_bench).css({display:'none'})
            }else{
                $(_bench).css({display:'grid'})
                _id = '.'+_label+' .output'
                $(_id)[0].spreadsheet.refresh()
                $(_id)[0].spreadsheet.hideFileMenuItems(["File"], true);
            }

        })        
    }  
   
    this._export = function(_label,spreadsheet){
        var uri = 'api/io/write'
        var http = HttpClient.instance()
        var _data = {}
        _rows = {}
        spreadsheet.sheets.forEach((sheet)=>{
            _rows[sheet.name] = {columns:[],values:[]}

            sheet.rows.forEach((_item,_index)=>{ 
                // cells = _item.cells
                if(_index == 0){
                    _item.cells.forEach(_x =>{
                        _rows[sheet.name].columns.push(_x.value)
                    })
                }else{
                    rec = []
                    _item.cells.forEach(_x=>{
                        rec.push(_x.value)
                    })
                    _rows[sheet.name].values.push(rec)
                }
            })
        })
        if (spreadsheet.chartColl.length > 0){
            _rows ['charts'] = spreadsheet.chartColl
        }
        if (_rows ){
            http.setHeader('Content-Type','application/json')
            http.setData (JSON.stringify({rows:_rows,'label':_label}))
            http.post(uri,(x)=>{
                if(x.status == 200 && x.readyState == 4){
                    //
                    //
                    // console.log(x)
                    // var blob = new Blob([x.response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
                    const byteCharacters = atob(x.responseText);
                    const byteNumbers = new Array(byteCharacters.length);
                    for (let i = 0; i < byteCharacters.length; i++) {
                        byteNumbers[i] = byteCharacters.charCodeAt(i);
                    }
                    const byteArray = new Uint8Array(byteNumbers);
                    const blob = new Blob([byteArray], {
                        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                    });
                                        
                    const link = document.createElement("a");
                    link.href = URL.createObjectURL(blob);
                    link.download = _label+'-export.xlsx';
                    document.body.appendChild(link);
                    link.click();

                    // Cleanup
                    URL.revokeObjectURL(link.href);
                    document.body.removeChild(link);
                    
                }else{
                    //
                    // something went wront
                }
            })
        }
    }
    this.export = function (_label,spreadsheet){
        // spreadsheet.save({filename:_label+'-export.xlsx'})
        uri = studio._context+'api/io/write'
        
        filename = _label+'.xlsx'
        spreadsheet.saveAsJson().then(response => {
            // const fd = new FormData();
            // fd.append('JSONData', JSON.stringify(response.jsonObject.Workbook));
            // fd.append('fileName', filename);
            form = {'JSONData':response.jsonObject.Workbook,'fileName':filename}
            // r = fetch(uri, { method: 'POST', body: fd });
            var http = HttpClient.instance()
            http.setHeader('Content-Type','application/json')
            http.setData ( JSON.stringify(form))
            http.post(uri,(x)=>{
                if(x.status == 200 && x.readyState == 4){
                    //
                    //
                    // console.log(x)
                    // var blob = new Blob([x.response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
                    const byteCharacters = atob(x.responseText);
                    const byteNumbers = new Array(byteCharacters.length);
                    for (let i = 0; i < byteCharacters.length; i++) {
                        byteNumbers[i] = byteCharacters.charCodeAt(i);
                    }
                    const byteArray = new Uint8Array(byteNumbers);
                    const blob = new Blob([byteArray], {
                        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                    });
                                        
                    const link = document.createElement("a");
                    link.href = URL.createObjectURL(blob);
                    link.download = _label+'-export.xlsx';
                    document.body.appendChild(link);
                    link.click();

                    // Cleanup
                    URL.revokeObjectURL(link.href);
                    document.body.removeChild(link);
                    
                }
            })
            
        });

    }
    
    this.render = function (){
        
        var _args = this._args
        var _importSheet = this.open
        var _exportSheet = this.export
        
        var _icon = $('<img>').attr('src',this._args.icon)
        _text = _args.provider
        if (_args.AI){
            //
            // The current technology supports AI
            _text = (parseInt(sessionStorage.AI) == 1)?(_text+', <b class="ai-workbench-status" style="color:#4682B4">AI Enabled </b>') : (_text+', <b <b class="ai-workbench-status" style="color:maroon">AI Disabled </b>') 
        }
        // _text = (_args.AI && sessionStorage.AI)? (_text+', <b style="color:#4682B4">AI Enabled </b>') : _text
        var _label = $('<div class="bold"></div>').html(this._args.label+'<div style="font-weight:lighter; font-size:11px;">'+_text+'</div>')
        read = this.read
        _compute = this.compute
        _xbutton = $('<div class="border-left"><div class="active apply" align="center" title="Run Query"><i class="fa-solid fa-play"></i></div></div>').on('click',function (){
            // var _id = '.code.'+_args.label.trim()
            // _query = $(_id).val()
            
            // if (_query.length != ''){
            //     var _data = read(_args,_query,_compute)
                

            // }
            
            var _child = $(`.${_args.label} .control .apply`).children()[0]
            if ($(_child).attr('class').match(/play/)){
                $(`.${_args.label} .control .apply`).empty()
                $(`.${_args.label} .control .apply`).append($('<i class="fa-solid fa-cog fa-spin" style="color:#FF6500"></i>'))

                //
                //
                 var _id = '.code.'+_args.label.trim()
                _query = $(_id).val()
            
                if (_query.length != ''){
                    var _data = read(_args,_query,_compute)
                    

                }

            }else{

            }
        })
       
        _pythonCode = $('<div class="border-left" title="Python Code"><div class="active" align="center"><img src="_assets/images/python.png" style="width:20px" /></div></div>')
        _pythonCode.on('click',()=>{
            
            
            _query = $(`.${_args.label} textarea`).val()
            
            
            sessionStorage._label = _args.label
            sessionStorage._query = _query
            var _kwargs = {uri:'www/html/python.html',title:'Generated Python Code',context:studio._context}
            dialog.show(_kwargs)

        })
        _openFile = $('<div class="border-left"><div class="active" title="Open File"><i class="fa-regular fa-folder-open"></i></div></div>')
        $(_openFile).on('click',()=>{
            var _id = '.'+_args.label+' .open-file'
            $(_id).on('change',(event)=>{
                var file = event.target.files[0]
                _id = '.'+_args.label + ' .output'
                _importSheet(_id,file)
            })
            $(_id).click()
        })
        _saveFile = $('<div class="border-left"><div class="active" title="Save File"><i class="fa-solid fa-floppy-disk"></i></div></div>')
        $(_saveFile).on('click',()=>{
            var _id = '.'+_args.label +' .output'
            var spreadsheet = $(_id)[0].spreadsheet
            _exportSheet(_args.label,spreadsheet)
        })
        _wizButton = $('<div class="border-left"><div class="active" title="New Connection"><i class="fa-solid fa-plug-circle-plus" style="color:#4682B4;"></i></div></div>')
        _wizButton.on('click',function(){
            dialog.show({uri:'www/html/wizard.html',title:'Create New Connection',context:studio._context})

        })
        _expandButton = $('<div class="border-left"><div class="active expand"><i class="fa-solid fa-angle-up" title="Expand spreadsheet"></div></div></div>')
        $(_expandButton).attr('label',_args.label)
        $(_expandButton).on('click',function(){
            var _id = '.studio.'+$(this).attr('label') // + ' .expand'
            if ($(_id).html().match(/fa-angle-up/)){
                _icon = '<i class="fa-solid fa-angle-down"></i>'
                _title = "Collapse Spreadsheet"
                $(_id).addClass('studio-expand')
            }else{
                _icon = '<i class="fa-solid fa-angle-up"></i>'
                $(_id).removeClass('studio-expand')
                _title = "Expand Spreadsheet"

            }
            $(_id+' .expand').empty().html(_icon).attr('title',_title)
            var spreadsheet = $(_id+' .output')[0].spreadsheet
            spreadsheet.refresh()
            spreadsheet.hideFileMenuItems(["File"], true);
        })
        
        var _buttons = $('<div style="display:grid; grid-template-columns: auto repeat(6,64px); gap:4px; align-items:center; align-content:center;" align="center"><div>&nbsp;</div></div>')
        _buttons.append(_pythonCode,_openFile,_saveFile,_wizButton,_xbutton,_expandButton)

        // _frame = $('<div class="studio :label"></div>'.replace(/:label/,this._args.label))
        var _frame = $('<div class="studio"></div>') .addClass(this._args.label)
        //
        // Input frame has 2 components (control, textarea)
        _ctrl = $('<div class="border control" align="left"></div>')
        _ctrl.append(_icon,_label,_buttons) //.html(this._args.label))
        _textarea = $('<textarea class="code"></textarea>').addClass(this._args.label).attr('label',_args.label)
        if (studio.defaults[_args.provider] != null){
            _query = studio.defaults[_args.provider]
            if (sessionStorage[_args.label]) {
                
                // _query = ('-- '+_query.replace(/\n/g,' ')+'\n') +  sessionStorage[_args.label]
                _query = sessionStorage[_args.label]
            }
            $(_textarea).val(_query)
        }
       
        $(_textarea).on('keydown',function (_e){
            if (/*_e.shiftKey*/ _e.ctrlKey && (_e.keyCode == 13 || _e.key == 'Enter'||_e.key == 'Return')){
                var _id = $(this).attr('label')
                _id = `.${_id} .apply`
                $(_id).click()
            }
        })
        
        _outputframe = $('<div class="output" ></div><div class="status"></div><input type="file" class="open-file" style="display:none" accept=".csv, .xls, .xlsx"/>')
        

        
        $(_frame).append(_ctrl,_textarea,_outputframe)
        $('.studio-pane').append(_frame)
        $(_textarea).focus()
        var _id = this._args.label
        _id = `.${_id} code`
        
        this.compute()
        $('.jxmodal').remove()
        

    }

    this.compute = function (_label,_data){
        _label = (_label != null)?_label: this._args.label
        _id = '.'+_label + ' .output'
        _data = (_data == null)? {'data':[],'columns':[]}: _data ;
        if (_data.data == null){
            _data = {data:[],columns:[]} //{'columns':[],'data':[[]]}
        }
        
        $(_id).empty()
        _gHandler = new studio.grid()
        _gHandler.syncfusion(_id,_data)
        _rows = (_data.data)?_data.data.length : 0
        $('.'+_label + ' .status').html(_rows + ' rows')
      
       
    }
}


studio.menu = {}
studio.menu.collapse = function (){
    $('.studio-index').removeClass('studio-index').addClass('studio-index-collapsed')
}
studio.menu.expand = function (){
    $('.studio-index-collapsed').removeClass('studio-index-collapsed').addClass('studio-index')
}

