import debounce from 'lodash-es/debounce';
import { api } from '@converse/headless';
import { applyDragResistance, getResizingDirection } from './utils.js';

const DragResizableMixin = {
    initDragResize () {
        const debouncedSetDimensions = debounce(() => this.setDimensions());
        window.addEventListener('resize', debouncedSetDimensions);
        this.listenTo(this.model, 'destroy', () => window.removeEventListener('resize', debouncedSetDimensions));

        // Determine and store the default box size.
        // We need this information for the drag-resizing feature.
        const flyout = this.querySelector('.box-flyout');
        const style = window.getComputedStyle(flyout);

        if (this.model.get('height') === undefined) {
            const height = parseInt(style.height.replace(/px$/, ''), 10);
            const width = parseInt(style.width.replace(/px$/, ''), 10);
            this.model.set('height', height);
            this.model.set('default_height', height);
            this.model.set('width', width);
            this.model.set('default_width', width);
        }
        const min_width = style['min-width'];
        const min_height = style['min-height'];
        this.model.set('min_width', min_width.endsWith('px') ? Number(min_width.replace(/px$/, '')) : 0);
        this.model.set('min_height', min_height.endsWith('px') ? Number(min_height.replace(/px$/, '')) : 0);
        // Initialize last known mouse position
        this.prev_pageY = 0;
        this.prev_pageX = 0;
        if (api.connection.get()?.connected) {
            this.height = this.model.get('height');
            this.width = this.model.get('width');
        }
        return this;
    },

    resizeChatBox (ev) {
        let diff;
        const direction = getResizingDirection();
        if (direction.indexOf('top') === 0) {
            diff = ev.pageY - this.prev_pageY;
            if (diff) {
                this.height =
                    this.height - diff > (this.model.get('min_height') || 0)
                        ? this.height - diff
                        : this.model.get('min_height');
                this.prev_pageY = ev.pageY;
                this.setChatBoxHeight(this.height);
            }
        }
        if (direction.includes('left')) {
            diff = this.prev_pageX - ev.pageX;
            if (diff) {
                this.width =
                    this.width + diff > (this.model.get('min_width') || 0)
                        ? this.width + diff
                        : this.model.get('min_width');
                this.prev_pageX = ev.pageX;
                this.setChatBoxWidth(this.width);
            }
        }
    },

    setDimensions () {
        // Make sure the chat box has the right height and width.
        this.adjustToViewport();
        this.setChatBoxHeight(this.model.get('height'));
        this.setChatBoxWidth(this.model.get('width'));
    },

    setChatBoxHeight (height) {
        if (height) {
            height = applyDragResistance(height, this.model.get('default_height')) + 'px';
        } else {
            height = '';
        }
        const flyout_el = this.querySelector('.box-flyout');
        if (flyout_el !== null) {
            flyout_el.style.height = height;
        }
    },

    setChatBoxWidth (width) {
        if (width) {
            width = applyDragResistance(width, this.model.get('default_width')) + 'px';
        } else {
            width = '';
        }
        this.style.width = width;
        const flyout_el = this.querySelector('.box-flyout');
        if (flyout_el !== null) {
            flyout_el.style.width = width;
        }
    },

    adjustToViewport () {
        /* Event handler called when viewport gets resized. We remove
         * custom width/height from chat boxes.
         */
        const viewport_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
        const viewport_height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
        if (viewport_width <= 480) {
            this.model.set('height', undefined);
            this.model.set('width', undefined);
        } else if (viewport_width <= this.model.get('width')) {
            this.model.set('width', undefined);
        } else if (viewport_height <= this.model.get('height')) {
            this.model.set('height', undefined);
        }
    }
};

export default DragResizableMixin;
