'use strict';

import * as chai from 'chai';
import {getDocument} from "../../../source/dom/util.mjs";
import {chaiDom} from "../../util/chai-dom.mjs";
import {cleanupDOMFromTesting, initMutationObserverForTesting} from "../../util/cleanupdom.mjs";
import {initJSDOM} from "../../util/jsdom.mjs";

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

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

describe('DOM', function () {

    let CustomControl, registerCustomElement, TestComponent, document, jsdomFlag;

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

            import("element-internals-polyfill").then((m) => {
                m.polyfill();
            });

            // jsdom does not support ElementInternals
            jsdomFlag = navigator.userAgent.includes("jsdom");

            import("../../../source/dom/customelement.mjs").then((m) => {

                registerCustomElement = m['registerCustomElement'];


                import("../../../source/dom/customcontrol.mjs").then((m) => {

                    document = getDocument();

                    try {
                        CustomControl = m['CustomControl'];

                        TestComponent = class extends CustomControl {
                            static getTag() {
                                return "monster-customcontrol"
                            }
                        }
                        registerCustomElement(TestComponent)
                        done()
                    } catch (e) {
                        done(e);
                    }


                });
            }).catch((e) => {
                done(e);
            });
        });
    })

    describe('formDisabledCallback()', function () {
        
        let element
        
        beforeEach(() => {
            try {
                const TestComponent2 = class extends CustomControl {
                    /**
                     * A description of the entire function.
                     *
                     * @return {string} description of return value
                     */
                    static getTag() {
                        return "monster-customcontrol2"
                    }
                }
                registerCustomElement(TestComponent2)
            } catch (e) {
                expect(e).to.be.not.null;
            }

             element = document.createElement('monster-customcontrol2');

        })
        
        afterEach(() => {

        })

        it('should return undefined', function () {
            expect(element.formDisabledCallback()).to.be.undefined;
            expect(element.hasAttribute('disabled')).to.be.false;
            expect(element.formDisabledCallback(true)).to.be.undefined;
            expect(element.hasAttribute('disabled')).to.be.true;
            const d = element.getAttribute('disabled');
            expect(d).to.not.be.null;
            
        });

    })


    describe('CustomControl()', function () {

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

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

        })

        describe('create', function () {
            it('should return custom-element object', function () {
                let d
                try {
                    d = new TestComponent();
                } catch (e) {
                    expect(e).to.be.null;
                }

                expect(typeof d).is.equal('object');
                
            });
        });

        describe('connect empty element', function () {
            it('document should contain monster-customcontrol', function () {

                let d = document.createElement('monster-customcontrol');
                document.getElementById('test1').appendChild(d);

                expect(document.getElementsByTagName('monster-customcontrol').length).is.equal(1);
                // no data-monster-objectlink="Symbol(monsterUpdater)" because it has nothing to update 
                expect(document.getElementById('test1')).contain.html('<monster-customcontrol data-monster-error="html is not set."></monster-customcontrol>')
            });
        });

        // describe('Options change', function () {
        //
        //     it('delegatesFocus should change from true to false', function (done) {
        //         let element = document.createElement('monster-customcontrol')
        //
        //         expect(element.getOption('delegatesFocus')).to.be.true;
        //         setTimeout(() => {
        //             element.setAttribute(ATTRIBUTE_OPTIONS, JSON.stringify({delegatesFocus: false}));
        //             setTimeout(() => {
        //                 expect(element.getOption('delegatesFocus')).to.be.false;
        //                 done();
        //             }, 10);
        //         }, 10);
        //
        //
        //     }).timeout(100);
        //
        // })

	        describe('Test ElementInternals', function () {

	            let form;

            beforeEach(() => {
                form = document.createElement('form');
            })

            it('formAssociated', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

                expect(d.constructor.formAssociated).to.be.true;

            });

            it('form', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

                expect(d.form).to.be.instanceof(HTMLFormElement)

                // if (jsdomFlag) {
                //     expect(() => d.form).to.throw(Error);
                // } else {
                //     expect(d.form).to.be.instanceof(HTMLFormElement)
                // }


            });

            it('value getter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

                expect(() => d.value).to.throw(Error);

            });

            it('value setter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

                expect(() => d.value = 4).to.throw(Error);

            });

            it('setFormValue', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

            });

            it('name getter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

                expect(d.name).to.be.null;

            });

            it('type getter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

                expect(d.type).to.be.equal('monster-customcontrol');

            });

            it('validity getter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);

            });

            it('validationMessage getter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);


            });

            it('willValidate getter', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);


            });
            it('checkValidity()', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);


            });

            it('reportValidity()', function () {

                let d = document.createElement('monster-customcontrol');
                form.appendChild(d);


            });


	            it('setValidity()', function () {

	                let d = document.createElement('monster-customcontrol');
	                form.appendChild(d);
	                expect(d.setValidity({'valueMissing': true}, "my message")).to.be.undefined;

	            });

	            it('formResetCallback() should restore the value attribute', function () {
	                const htmlTAG = 'monster-customcontrol-reset';

	                class ResetComponent extends CustomControl {
	                    static getTag() {
	                        return htmlTAG;
	                    }

	                    get defaults() {
	                        return Object.assign({}, super.defaults, {
	                            shadowMode: false,
	                        });
	                    }

	                    get value() {
	                        return this._value ?? '';
	                    }

	                    set value(value) {
	                        this._value = value;
	                    }
	                }

	                registerCustomElement(ResetComponent);

	                let d = document.createElement(htmlTAG);
	                d.setAttribute('value', 'seed');
	                d.value = 'changed';
	                form.appendChild(d);

	                d.formResetCallback();

	                expect(d.value).to.equal('seed');
	            });


	        });
	    });

});

