import {getGlobal} from "../../../../source/types/global.mjs";
import * as chai from 'chai';
import {chaiDom} from "../../../util/chai-dom.mjs";
import {initJSDOM} from "../../../util/jsdom.mjs";

let expect = chai.expect;
chai.use(chaiDom);

const global = getGlobal();

let html1 = `
    <div id="test1">
    </div>
`;

let html2 = `
    <div id="test2">
         <monster-toggle-switch></monster-toggle-switch>
    </div>
`;

let ToggleSwitch;

describe('ToggleSwitch', function () {

    before(function (done) {
        initJSDOM().then(() => {

            import("element-internals-polyfill").catch(e => done(e));

            import("../../../../source/components/form/toggle-switch.mjs").then((m) => {
                ToggleSwitch = m['ToggleSwitch'];
                done()
            }).catch(e => done(e))


        });
    })

    describe('new ToggleSwitch', function () {

        beforeEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = html1;
        })

        afterEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = "";
        })

        describe('create from template', function () {
            beforeEach(() => {
                let mocks = document.getElementById('mocks');
                mocks.innerHTML = html2;
            });

            afterEach(() => {
                let mocks = document.getElementById('mocks');
                mocks.innerHTML = "";

            })

            describe('create from template', function () {
                it('should contains monster-toggle-switch', function () {
                    expect(document.getElementById('test2')).contain.html('<monster-toggle-switch');
                });
            });

        });

        describe('document.createElement', function () {
            it('should instance of monster-toggle-switch', function () {
                expect(document.createElement('monster-toggle-switch')).is.instanceof(ToggleSwitch);
            });
        });

    });

    describe('toggle', function () {
        beforeEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = html1;
        });

        afterEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = "";
        })

        it('toggle to on', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');
            toggleSwitch.setOption('values.on', 'true');
            toggleSwitch.setOption('values.off', 'false');

            toggleSwitch.value = "true";

            expect("true").is.equal(toggleSwitch.value);
            expect("on").is.equal(toggleSwitch.state);

            toggleSwitch.toggle();

            expect("false").is.equal(toggleSwitch.value);
            expect("off").is.equal(toggleSwitch.state);

            toggleSwitch.toggle();

            expect("true").is.equal(toggleSwitch.value);
            expect("on").is.equal(toggleSwitch.state);

        });

        it('toggle on to off', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');

            toggleSwitch.toggleOn();

            expect(toggleSwitch.value).is.equal('on');
            expect(toggleSwitch.state).is.equal('on');

            toggleSwitch.toggleOff();

            expect(toggleSwitch.value).is.equal('off');
            expect(toggleSwitch.state).is.equal('off');

        });


    });

    describe('describe css', function () {

        beforeEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = html1;
        });

        afterEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = "";
        })

        it('css toggle', function (done) {

            /**
             * new Control
             */
            const toggleSwitch = document.createElement('monster-toggle-switch');

            /**
             * set init value to on
             */
            toggleSwitch.value = "on";

            /**
             * insert DOM
             */
            document.getElementById('mocks').appendChild(toggleSwitch);

            /**
             * Updater prozess runs in setTimeout
             * self[internalSymbol].attachObserver();
             */
            setTimeout(() => {

                window.requestAnimationFrame(() => {

                    /**
                     * expect that classes.on is set to Element Switch
                     */
                    let hasClassA = toggleSwitch.shadowRoot.querySelectorAll('[data-monster-role="switch"]')[0].classList.contains(toggleSwitch.getOption('classes.on'));


                    expect(hasClassA).is.true;

                    /**
                     * switch off
                     */
                    toggleSwitch.value = "off";

                    window.requestAnimationFrame(() => {
                        /**
                         * expect that classes.on is removed from Element Switch
                         */
                        let hasClassB = toggleSwitch.shadowRoot.querySelectorAll('[data-monster-role="switch"]')[0].classList.contains(toggleSwitch.getOption('classes.on'));
                        expect(hasClassB).is.false;

                        /**
                         * expect that classes.off is set to Element Switch
                         */
                        let hasClassC = toggleSwitch.shadowRoot.querySelectorAll('[data-monster-role="switch"]')[0].classList.contains(toggleSwitch.getOption('classes.off'));
                        expect(hasClassC).is.true;


                        done();
                    });

                });

            }, 0);

        })

    });

    describe('describe value', function () {

        beforeEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = html1;
        });

        afterEach(() => {
            let mocks = document.getElementById('mocks');
            mocks.innerHTML = "";

        })

        it('the default value is off', function () {

            /**
             * new Control
             */
            let toggleSwitch = document.createElement('monster-toggle-switch');
            window.requestAnimationFrame(() => {

                /**
                 * the switch is off and provides the value for off
                 */
                expect(null).is.equal(toggleSwitch.value);

                /**
                 * the switch is off
                 */
                expect(toggleSwitch.state).is.equal('off');
            });

        });

        it('incorrect values are not accepted', function () {

            let toggleSwitch = document.createElement('monster-toggle-switch');

            /**
             * define the values for on and off
             */
            toggleSwitch.setOption('values.on', 'true');
            toggleSwitch.setOption('values.off', 'false');

            /**
             * This value is not "true" and not "false"
             */
            toggleSwitch.value = "test";

            window.requestAnimationFrame(() => {

                /**
                 * the switch is off and provides the value for off
                 */
                expect(null).is.equal(toggleSwitch.value);

                /**
                 * the switch is off
                 */
                expect(toggleSwitch.state).is.equal('off');

                /**
                 * disabled attribute is only set when the element has been mounted in the DOM
                 */
                expect(toggleSwitch.hasAttribute('disabled')).is.false;

                /**
                 * insert DOM
                 */
                document.getElementById('mocks').appendChild(toggleSwitch);

                /**
                 * now the element is disabled
                 */
                expect(toggleSwitch.hasAttribute('disabled')).is.false;
            });

        });

        it('correct values are accepted', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');

            /**
             * define the values for on and off
             */
            toggleSwitch.setOption('values.on', 'true');
            toggleSwitch.setOption('values.off', 'false');

            /**
             * This value is correct
             */
            toggleSwitch.value = "true";

            /**
             * the switch is on and provides the value for on
             */
            expect(toggleSwitch.value).is.equal('true');

            /**
             * the switch is on
             */
            expect(toggleSwitch.state).is.equal('on');

            /**
             * insert DOM
             */
            document.getElementById('mocks').appendChild(toggleSwitch);

            /**
             * disabled attribute is not set
             */
            expect(toggleSwitch.hasAttribute('disabled')).is.false;

        });

        it('normalizes on/off to configured true/false values', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');

            toggleSwitch.setOption('values.on', 'true');
            toggleSwitch.setOption('values.off', 'false');

            toggleSwitch.value = "on";

            expect(toggleSwitch.value).is.equal('true');
            expect(toggleSwitch.state).is.equal('on');

            toggleSwitch.value = "off";

            expect(toggleSwitch.value).is.equal('false');
            expect(toggleSwitch.state).is.equal('off');

        });

        it('normalizes true/false to configured on/off values', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');

            toggleSwitch.setOption('values.on', 'on');
            toggleSwitch.setOption('values.off', 'off');

            toggleSwitch.value = true;

            expect(toggleSwitch.value).is.equal('on');
            expect(toggleSwitch.state).is.equal('on');

            toggleSwitch.value = false;

            expect(toggleSwitch.value).is.equal('off');
            expect(toggleSwitch.state).is.equal('off');

        });

        it('normalizes when on/off are inverted', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');

            toggleSwitch.setOption('values.on', 'off');
            toggleSwitch.setOption('values.off', 'on');

            toggleSwitch.value = "on";

            expect(toggleSwitch.value).is.equal('on');
            expect(toggleSwitch.state).is.equal('off');

            toggleSwitch.value = "off";

            expect(toggleSwitch.value).is.equal('off');
            expect(toggleSwitch.state).is.equal('on');

        });

        it('normalizes when true/false are inverted', function () {

            const toggleSwitch = document.createElement('monster-toggle-switch');

            toggleSwitch.setOption('values.on', 'false');
            toggleSwitch.setOption('values.off', 'true');

            toggleSwitch.value = true;

            expect(toggleSwitch.value).is.equal('true');
            expect(toggleSwitch.state).is.equal('off');

            toggleSwitch.value = false;

            expect(toggleSwitch.value).is.equal('false');
            expect(toggleSwitch.state).is.equal('on');

        });

        it('does not set error state for empty initial values', function (done) {

            const toggleSwitch = document.createElement('monster-toggle-switch');
            toggleSwitch.setOption('value', undefined);
            document.getElementById('mocks').appendChild(toggleSwitch);

            setTimeout(() => {
                const switchEl = toggleSwitch.shadowRoot.querySelector('[data-monster-role="switch"]');
                expect(toggleSwitch.getAttribute('data-monster-error')).is.equal(null);
                expect(switchEl.classList.contains(toggleSwitch.getOption('classes.error'))).is.false;
                expect(toggleSwitch.value).is.equal(toggleSwitch.getOption('values.off'));
                done();
            }, 0);
        });

    });


});
