import UserUtil from "../../../Utils/UserUtil";
import Utils from "../../../Utils/Utils";
import EventBus, { Events, Event } from '../../../Events/EventBus';
import Player from "../../../BackgroundJobs/Player";

const CanPlayStatus = {
    FREE_TO_PLAY: 'FREE_TO_PLAY',
};

class SoundUI {
    _slider;
    _handle;
    currentVolumePercentage = 0;
    image_ui;
    isPlaying = false;
    soundInfo;
    defaultVolume = 50;
    infoPopup;
    onPlayPauseChangeCb;
    _component_base_ui;
    _canPlayStatus = '';

    constructor(component_base_ui, soundInfo, onPlayPauseChangeCb) {
        this._component_base_ui = component_base_ui;
        this.onPlayPauseChangeCb = onPlayPauseChangeCb;
        this._slider = this._component_base_ui.find('.volume-slider');
        this._handle = this._component_base_ui.find('.handle');
        this.image_ui = this._component_base_ui.find('.playlist-img-ui');

        this.soundInfo = soundInfo;
        this.defaultVolume = this.soundInfo?.soundVolume || this.defaultVolume;
        
        this.init();
    }

    init() {
        this._canPlayStatus = CanPlayStatus.FREE_TO_PLAY;
        this.handleSound()
    }

    handleSound() {
        const url = this.soundInfo?.soundFileUrl;

        this._handleUIEvents();

        if (this.defaultVolume) {
            setTimeout(() => {
                this.setVolume(this.defaultVolume);
            }, 300);
        }
    }

    _handleRestrictedEvents(options = {}) {
        const _this = this;
        this._component_base_ui.find('.playlist-img-ui').on('click', function(event) {
            event.preventDefault();
            _this._restrictedEventsClick(options);
        });
        this._component_base_ui.find('.pro-sound').on('click', function(event) {
            event.preventDefault();
            _this._restrictedEventsClick(options);
        });
        this._component_base_ui.find('.login-sound').on('click', function(event) {
            event.preventDefault();
            _this._restrictedEventsClick(options);
        });
    }

    _restrictedEventsClick(options = {}) {
        const { loginRequired, proRequired } = options;
        let eventType = '';
        if (loginRequired) {
            eventType = Events.SOUND_LOGIN_REQUIRED_POPUP;
        }
        if (proRequired) {
            eventType = Events.SOUND_PRO_REQUIRED_POPUP;
        }
        EventBus.getInstance().triggerEvent(
            eventType, {}
        );
    }

    _handleUIEvents() {

        const _this = this;

        this._handle.draggable({
            axis: "x",
            containment: 'parent',
            drag: function (event, ui) {
                const position = ui.position.left;
                const sdWidth = _this._slider.width();
                const maxWidth = sdWidth - _this._handle.width();
                const perc = Math.round((position / maxWidth) * 100);
                if (!isNaN(perc)) {
                    _this.setVolume(perc);
                } else {
                    throw new Error("Invalid percentage");
                }
            }
        });

        // Add touch event handlers for mobile support
        this._initTouchDrag();

        this.image_ui.on('click', () => {
            this.setStatus(!this.isPlaying);
        })

        this._component_base_ui.find('.sound-name').on('click', event => {
            this.setStatus(!this.isPlaying);
        })

        const windowResize = new Event(
            Events.WINDOW_RESIZE,
            (payload) => { this.setVolume(this.currentVolumePercentage) }
        );
        EventBus.getInstance().registerEvent(windowResize);
    }

    _initTouchDrag() {
        const _this = this;
        let isDragging = false;
        let startX = 0;
        let startLeft = 0;

        const handleElement = this._handle[0];

        handleElement.addEventListener('touchstart', function(e) {
            isDragging = true;
            const touch = e.touches[0];
            startX = touch.clientX;
            startLeft = parseInt(_this._handle.css('left')) || 0;
            e.preventDefault();
        }, { passive: false });

        document.addEventListener('touchmove', function(e) {
            if (!isDragging) return;

            const touch = e.touches[0];
            const deltaX = touch.clientX - startX;
            const newLeft = startLeft + deltaX;

            const sliderWidth = _this._slider.width();
            const handleWidth = _this._handle.width();
            const maxLeft = sliderWidth - handleWidth;

            let constrainedLeft = Math.max(0, Math.min(newLeft, maxLeft));

            const perc = Math.round((constrainedLeft / maxLeft) * 100);

            if (!isNaN(perc)) {
                _this.setVolume(perc);
            }

            e.preventDefault();
        }, { passive: false });

        document.addEventListener('touchend', function(e) {
            if (isDragging) {
                isDragging = false;
            }
        });

        document.addEventListener('touchcancel', function(e) {
            if (isDragging) {
                isDragging = false;
            }
        });
    }

    canPlaySound() {
        if (!this.soundInfo?.soundFileUrl) {
            return false;
        }
        if (this.soundInfo?.soundFileUrl === '') {
            return false;
        }
        if (this._canPlayStatus !== CanPlayStatus.FREE_TO_PLAY) {
            return false;
        }
        return true;
    }

    setVolume(percentage) {
        this.currentVolumePercentage = percentage;
        const sdWidth = this._slider.width();
        const maxWidth = sdWidth - this._handle.width();
        const left = (percentage / 100) * maxWidth;
        this._handle.css('left', left);

        if (Utils.isValidNumber(percentage)) {
            Player.getInstance().setSoundVolume(this.soundInfo, percentage / 100)
        }
        if (Utils.isFunction(this.onPlayPauseChangeCb)) {
            this.onPlayPauseChangeCb();
        }
    }

    setStatus(status) {
        this.isPlaying = status;
        if (status) {
            this.image_ui.removeClass('inactive-sound-opacity');
            this._slider.css('opacity', 1);
            Player.getInstance().playSound(this.soundInfo)
        } else {
            this.image_ui.addClass('inactive-sound-opacity');
            this._slider.css('opacity', 0);
            Player.getInstance().pauseSound(this.soundInfo)
        }
        if (Utils.isFunction(this.onPlayPauseChangeCb)) {
            this.onPlayPauseChangeCb({
                isPlaying: this.isPlaying, ...this.soundInfo, currentVolumePercentage: this.currentVolumePercentage,
            });
        }
    }

    getSoundInfo() {
        return this.soundInfo;
    }
}

export default SoundUI;