import $ from 'jquery';
import Cookies from '../utils/cookies';

const MOBILE_BREAKPOINT = 48 - 0.062;
const DESKTOP_BREAKPOINT = 75 + 0.063;
const EVENTS = 'touchstart._grav click._grav';
const TARGETS = '[data-sidebar-mobile-toggle], #overlay';
const MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT}em)`;
const DESKTOP_QUERY = `(min-width: ${DESKTOP_BREAKPOINT}em)`;

let map = new global.Map();

export default class Sidebar {
    constructor() {
        this.timeout = null;
        this.isOpen = false;
        this.body = $('body');
        this.matchMedia = global.matchMedia(MOBILE_QUERY);
        this.enable();
    }

    enable() {
        const sidebar = $('#admin-sidebar');

        this.matchMedia.addListener(this._getBound('checkMatch'));
        this.checkMatch(this.matchMedia);
        this.body.on(EVENTS, '[data-sidebar-toggle]', this._getBound('toggleSidebarState'));

        if (sidebar.data('quickopen')) {
            sidebar.hover(this._getBound('quickOpenIn'), this._getBound('quickOpenOut'));
        }
    }

    disable() {
        const sidebar = $('#admin-sidebar');

        this.close();
        this.matchMedia.removeListener(this._getBound('checkMatch'));
        this.body.off(EVENTS, '[data-sidebar-toggle]', this._getBound('toggleSidebarState'));
        if (sidebar.data('quickopen')) {
            sidebar.off('mouseenter mouseleave');
        }
    }

    attach() {
        this.body.on(EVENTS, TARGETS, this._getBound('toggle'));
    }

    detach() {
        this.body.off(EVENTS, TARGETS, this._getBound('toggle'));
    }

    quickOpenIn(/* event */) {
        let isDesktop = global.matchMedia(DESKTOP_QUERY).matches;
        let delay = $('#admin-sidebar').data('quickopen-delay') || 500;
        if (this.body.hasClass('sidebar-mobile-open')) { return; }

        let shouldQuickOpen = isDesktop ? this.body.hasClass('sidebar-closed') : !this.body.hasClass('sidebar-open');
        if (!shouldQuickOpen && !this.body.hasClass('sidebar-quickopen')) { return this.quickOpenOut(); }

        this.timeout = setTimeout(() => {
            this.body.addClass('sidebar-open sidebar-quickopen');
            $(global).trigger('sidebar_state._grav', isDesktop);
        }, delay);
    }

    quickOpenOut(/* event */) {
        clearTimeout(this.timeout);
        if (this.body.hasClass('sidebar-quickopen')) {
            this.body.removeClass('sidebar-open sidebar-quickopen');
        }

        return true;
    }

    open(event, quick = false) {
        if (event) { event.preventDefault(); }
        let overlay = $('#overlay');
        let sidebar = $('#admin-sidebar');

        this.body.addClass('sidebar-mobile-open');
        overlay.css('display', 'block');

        if (!quick) {
            sidebar.css('display', 'block').animate({
                opacity: 1
            }, 200, () => {
                this.isOpen = true;
            });
        } else {
            sidebar.css({ display: 'block', opacity: 1 });
            this.isOpen = true;
        }
    }

    close(event, quick = false) {
        if (event) { event.preventDefault(); }
        let overlay = $('#overlay');
        let sidebar = $('#admin-sidebar');

        this.body.removeClass('sidebar-mobile-open');
        overlay.css('display', 'none');

        if (!quick) {
            sidebar.animate({
                opacity: 0
            }, 200, () => {
                sidebar.css('display', 'none');
                this.isOpen = false;
            });
        } else {
            sidebar.css({ opacity: 0, display: 'none' });
            this.isOpen = false;
        }
    }

    toggle(event) {
        if (event) { event.preventDefault(); }
        return this[this.isOpen ? 'close' : 'open'](event);
    }

    toggleSidebarState(event) {
        if (event) { event.preventDefault(); }
        clearTimeout(this.timeout);
        let isDesktop = global.matchMedia(DESKTOP_QUERY).matches;
        let cookie = null;

        if (isDesktop) {
            this.body.removeClass('sidebar-open');
        }

        if (!isDesktop) {
            this.body.removeClass('sidebar-closed');
            this.body.removeClass('sidebar-mobile-open');
        }

        this.body.toggleClass(`sidebar-${isDesktop ? 'closed' : 'open'}`);
        $(global).trigger('sidebar_state._grav', isDesktop);

        if (isDesktop) {
            cookie = !this.body.hasClass('sidebar-closed');
        } else {
            cookie = this.body.hasClass('sidebar-open');
        }

        Cookies.set('grav-admin-sidebar', cookie, { expires: Infinity });
    }

    checkMatch(data) {
        let sidebar = $('#admin-sidebar');
        let overlay = $('#overlay');
        this.isOpen = false;

        overlay.css('display', 'none');
        sidebar.css({
            display: data.matches ? 'none' : 'inherit',
            opacity: data.matches ? 0 : 1
        });

        if (data.matches) {
            this.body.removeClass('sidebar-open sidebar-closed');
        }

        this[data.matches ? 'attach' : 'detach']();
    }

    _resetMap() {
        return map.clear();
    }

    _getBound(fn) {
        if (map.has(fn)) {
            return map.get(fn);
        }

        return map.set(fn, this[fn].bind(this)).get(fn);
    }
}

export let Instance = new Sidebar();
