/**
 * @category MyEic
 * @subcategory Libraries
 * @extends View
 */
class WindozDomContent extends View {
    
    icon = null;
    
    /**
     * 
     */
    loadContent(name, options, data) { return this._controller.loadContent(name, options, data); }

    get expanded() { return this.el.hasAttribute('expanded'); }

    _saveWindowBox(){
        const box = this.el.getBoundingClientRect()
        this.savedWindowBox = {
                    width: `${box.width}px`,
                    height: `${box.height}px`,
                    left: `${box.x}px`,
                    top: `${box.y}px`,
        }
    }


    /**
     * 
     */
    expand() { 
        this._saveWindowBox()
        this.el.setAttribute('expanded',''); 
        this.el.dispatchEvent(new CustomEvent('expanded'));
        this.el.style.left = 'auto';
        this.el.style.top = 'auto';
        this.el.style.height = 'auto';
        this.el.style.width = 'auto';

        this.DOMContentResized()
    }

    /**
     * 
     */
    shrink() { 
        this.el.removeAttribute('expanded'); 
        this.el.dispatchEvent(new CustomEvent('shrinked'));
        Object.assign(this.el.style, this.savedWindowBox)
        // this.el.style.left = this.el.getBoundingClientRect().x;
        // this.el.style.top = this.el.getBoundingClientRect().y;

        this.DOMContentResized();
    }

    openDialog(view) {
        let promise = new Promise(function(resolve) {
            if(typeof view === 'string') {
                let content = view;
                view = new WindozDialogContent();
                view.el = content;
            }

            let dialog = WindozController.createDialog(view);

            function commit(result) {
                WindozController.closeDialog(view._sparcId);
                resolve(result);
            }

            function abort(result) {
                WindozController.closeDialog(view._sparcId);
                resolve(result);
            }

            view.commit = commit;
            view.abort = abort;
            view.buttons.forEach(function(button) { 
                dialog.querySelector('[eicdialog] > [eiccard] > footer').append(button.el); 
            });
            
            view.DOMContentFocused();
            view.DOMContentResized();
        });

        return promise;
    }

    unload() { 
        let button = this.el.closest('.window').querySelector('.controls .close')
        if(button) button.click(); 
    }

    /**
     * 
     */
    initWindowEvents() {
        this.draggable(this.el);
        this.resizable(this.el, this.DOMContentResized.bind(this));
    }

    draggable(element) {
        let mouseX, mouseY, offsetX = 0, offsetY = 0;
    
        // mouse button down over the element
        element.querySelector('header h1').addEventListener('mousedown', onMouseDown.bind(this));
    
        /**
         * Listens to `mousedown` event.
         *
         * @param {Object} event - The event.
         */
        function onMouseDown(event) { 
            event.stopPropagation();
            event.preventDefault();

            mouseX = event.clientX;
            mouseY = event.clientY;
            offsetX = element.getBoundingClientRect().x;
            offsetY = element.getBoundingClientRect().y;
            
            document.addEventListener('mousemove', onMouseMove);
            element.addEventListener('mouseup', onMouseUp.bind(this));
        }
    
    
        /**
         * Listens to `mouseup` event.
         *
         * @param {Object} event - The event.
         */
        function onMouseUp(event) {
            offsetX = parseInt(element.style.left) || 0;
            offsetY = parseInt(element.style.top) || 0;
            document.removeEventListener('mousemove', onMouseMove);
            element.removeEventListener('mouseup', onMouseUp);
            if(this.windowPrefsId){
                const box = element.getBoundingClientRect()
                app.User.setPreference(`windows.${this.windowPrefsId}`, {
                    x: box.x,
                    y: box.y,
                });
            }
        }
    
        /**
         * Listens to `mousemove` event.
         *
         * @param {Object} event - The event.
         */
        function onMouseMove(event) {
            if(event.buttons != 1) {
                document.removeEventListener('mousemove', onMouseMove);
                return;
            }
            
            let dX = event.clientX - mouseX;
            let dY = event.clientY - mouseY;
            element.style.left = offsetX + dX + 'px';
            element.style.top = offsetY + dY + 'px';
        }
    }
    
    resizable(element, onResize) {
        let mouseX, mouseY, offset = 0, offsetY = 0, grab = '';

        element.querySelectorAll(':scope > .handle').forEach(handle => handle.addEventListener('mousedown', onMouseDown.bind(this)))

        element.querySelector('section').addEventListener('mousedown', onBlockMouseDown);
        
        function onBlockMouseDown(event) { event.stopPropagation(); }
        /**
         * mousedown event listener
         *
         * @param {Object} event - mouse event.
         */
        function onMouseDown(event) { 
            event.stopPropagation();
            event.preventDefault();

            if(event.currentTarget.parentElement.hasAttribute('expanded')) return false;

            let limits = element.getBoundingClientRect();
            
            mouseX = event.clientX;
            mouseY = event.clientY;
            
            grab = event.currentTarget.dataset.side

            offset = element.getBoundingClientRect();

            document.addEventListener('mousemove', onMouseMove);
            element.addEventListener('mouseup', onMouseUp.bind(this));
        }
    
    
        /**
         * mouseup event listener
         *
         * @param {Object} event - The event.
         */
        function onMouseUp(event) { 
            document.removeEventListener('mousemove', onMouseMove); 
            element.removeEventListener('mouseup', onMouseUp); 
            if(this.windowPrefsId){
                const box = element.getBoundingClientRect()
                app.User.setPreference(`windows.${this.windowPrefsId}`, {
                    w: box.width,
                    h: box.height,
                });
            }
        }
    
        /**
         * Listens to `mousemove` event.
         *
         * @param {Object} event - The event.
         */
        function onMouseMove(event) {

            if(event.buttons != 1) {
                document.removeEventListener('mousemove', onMouseMove);
                return;
            }
            
            let dx = event.clientX - mouseX;
            let dy = event.clientY - mouseY;
            mouseX = event.clientX;
            mouseY = event.clientY;

            if(grab.indexOf('n') > -1) { 
                offset.y = offset.y + dy; 
                offset.height = offset.height - dy; 
            }
            if(grab.indexOf('s') > -1) { 
                offset.height = offset.height + dy; 
            }
            if(grab.indexOf('w') > -1) { 
                offset.x = offset.x + dx; 
                offset.width = offset.width - dx; 
            }
            if(grab.indexOf('e') > -1) { 
                offset.width = offset.width + dx; 
            }
            
            element.style.left = offset.x + 'px';
            element.style.top = offset.y + 'px';
            element.style.height = offset.height + 'px';
            element.style.width = offset.width + 'px';

            onResize();
        }
    }

    DOMContentResized() {
        let limits = [ 
            { name: 'desktop', min: 768 }, 
            { name: 'tablet', min: 600 }, 
            { name: 'mobile', min: 0 } 
        ];
        let bounds = this.el.getBoundingClientRect();
        let device = limits.find(item => item.min < bounds.width);
        this.el.setAttribute('device', device ? device.name: limits[0].name);
    }

    static boxFromPrefs(viewName, defaults){
        function getPref(path) {
            return path.split('.').reduce(
                (acc, key) => acc?.[key],
                app.User.preferences.windows
            )
        }
        let top, left, width, height
        const box = getPref(viewName)
        if(box){
            left = box.x ? box.x : defaults.x
            top = box.y ? box.y : defaults.y
            width = box.w ? box.w : defaults.w
            height = box.x ? box.h : defaults.h
        } else {
            left = defaults.x
            top = defaults.y
            width = defaults.w
            height = defaults.h        
        }
        return({
                    width: `${width}px`,
                    height: `${height}px`,
                    left: `${left}px`,
                    top: `${top}px`,
        })
    }
}

app.registerClass('WindozDomContent', WindozDomContent);