/** This file is part of Reactor.
 *  Copyright (c) 2020-2025 Kedron Holdings LLC, All Rights Reserved.
 *  Reactor is not public domain or open source. Distribution or derivative works are expressly prohibited.
 */

export const version = 25141;

import Expression from '/client/Expression.js';

import { coalesce, showSysModal } from './reactor-ui-common.js';

import Tab from "./tab.js";
import ExpressionEditor from "./expression-editor.js";

import { _T } from './i18n.js';

/* ??? Need conversion to Tab class */

export default (function($) {

    var tabInstance = false;

    class ExpressionsTab extends Tab {
        constructor( $parent ) {
            super( 'tab-expressions', $parent );

            this.editor = false;
        }

        async activate( event ) {  // eslint-disable-line no-unused-vars
            // console.log("ReactorUIExpressions.activate() running");
            // console.log(event);
            const self = this;
            const $tab = this.getTabElement();
            $tab.empty();

            /* We head straight into the editor on this one. */
            const $ct = $('<div class="container-fluid re-editor-controls"></div>' ).appendTo( $tab );
            const $row = $( '<div class="re-listhead row align-middle pt-1"></div>' ).appendTo( $ct );
            $( `<div class="col ps-0"><h2>${_T(['Global Expressions'])}</h2></div>` )
                .appendTo( $row );
            $( `<div class="col text-end mt-2">
      <button class="btn btn-sm btn-success saveconf savecont">${_T('Save Changes')}</button>
      <button class="btn btn-sm btn-warning revertconf">${_T('Revert')}</button>
    </div>` ).appendTo( $row );
            $tab.data( 'mode', 'edit' ).attr( 'data-mode', 'edit' );
            $( 'btn', $row ).prop( 'disabled', true );

            const expressions = await Expression.getGlobalExpressions();
            const exp = {};
            expressions.forEach( expr => {
                exp[ expr.name ] = expr.getDataObject().value;
            });
            this.editor = new ExpressionEditor( exp, $tab, { isGlobal: true } );
            this.editor.editor().on( 'update-controls', function( ev, ui ) {
                /* During editing, various changes make the expression saveable, or not. */
                // console.log("got update-controls", ui);
                $( 'button.saveconf', $tab ).prop( 'disabled', ui.errors || !ui.modified );
                $( 'button.revertconf', $tab ).prop( 'disabled', !ui.modified );
            }).on( 'close', function() {
                // console.log("expression editor got close");
                $tab.data( 'mode', '' ).attr( 'data-mode', '' );
            }).on( 'modified', function( ev, ui ) {
                /* Sent when the cached expression is modified (no errors) */
                // console.log("got modified", ui);
                $( 'button.saveconf', $tab ).prop( 'disabled', ui.errors || !ui.modified );
                $( 'button.revertconf', $tab ).prop( 'disabled', !ui.modified );
            }).on( 'ready', function() {
                $( 'button.saveconf', $ct ).on( 'click', async function( event ) {  // eslint-disable-line no-unused-vars
                    // const $el = $( event.currentTarget );
                    if ( ! self.editor.canSave() ) {
                        showSysModal( {
                            title: _T('#dialog-error-title'),
                            body: _T('Fix errors before saving')
                        } );
                        return;
                    }
                    /* Get the current list of expressions */
                    let curr_exp = await Expression.getGlobalExpressions();
                    /* And what's in the editor */
                    let edit_exp = self.editor.current();
                    let newexp = {};
                    Object.values( edit_exp ).forEach( expr => { newexp[expr.name] = expr; } );
                    let promises = [];
                    curr_exp.forEach( expr => {
                        if ( edit_exp[ expr.name ] ) {
                            /* In editor, update */
                            delete newexp[ expr.name ];
                            let dobj = expr.getDataObject();
                            if ( edit_exp[ expr.name ].__modified ) {
                                dobj.value.expr = edit_exp[ expr.name ].expr || "";
                                if ( edit_exp[ expr.name ].noautoeval ) {
                                    dobj.value.noautoeval = true;
                                } else {
                                    delete dobj.value.noautoeval;
                                }
                                dobj.value.index = coalesce( edit_exp[ expr.name ].index, 32767 );
                                dobj.value.serial = (dobj.value.serial || 0) + 1;
                                dobj.value.mdt = Date.now();
                                dobj.value.editor_version = self.editor.version;
                                promises.push( dobj.forceModified().save() );
                            }
                        } else {
                            /* Not in editor, delete */
                            promises.push( expr.delete() );
                        }
                    });
                    /* Anything left in newexp is new */
                    Object.values( newexp ).forEach( ex => {
                        console.log("New experession", ex);
                        promises.push( Expression.create( ex.name, ex.expr || "", coalesce( ex.index, 32767 ) ) );
                    });
                    Promise.all( promises ).then( () => {
                        self.editor.notifySaved();
                    }).catch( err => {
                        showSysModal( {
                            title: _T('#dialog-error-title'),
                            body: _T('The save failed; try again. {0}', String(err))
                        } );
                        console.log(err);
                        $( 'button.saveconf', $tab ).prop( 'disabled', false );
                    });
                });
                $( 'button.revertconf', $ct ).on( 'click', function( event ) {  // eslint-disable-line no-unused-vars
                    self.editor.revert();
                });
            });
            this.editor.edit();
        }

        canSuspend() {
            if ( this.editor && this.editor.isModified() ) {
                return false;
            }
            return super.canSuspend();
        }

        suspending() {
            if ( this.editor ) {
                console.log("Closing", this.editor);
                this.editor.close();
                this.editor = false;
            }
            this.getTabElement().removeData( 'mode' ).attr( 'data-mode', null );
        }

    } /* class ExpressionsTab */

    return {
        "init": function( $main ) {
            if ( ! tabInstance ) {
                tabInstance = new ExpressionsTab( $main );
            }
        },
        "tab": () => tabInstance.getTabElement()
    };
})(jQuery);
