import { DOM, configure, IElement, template, customElement, bindable } from 'mframejs';
import { JSDOM } from 'jsdom';

let dummyArrayNew: any[] = [];
let dummyArrayOld: any[] = [];

// our dummy app to simplify parts
// a lot of repeats to see it just does not break
// todo add more classes and check ever repeat
export class App implements IElement {
    public arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    public obj = {
        arr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    };
    public loadTemplate() {
        return template`
            <div>
                <button class="button01" click.trigger="reverse()">reverse</button>
                <button class="button02" click.trigger="clear()">clear</button>
                <br/>
                <div class="lengths">@{arr.length + obj.arr.length}</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <div class="lengthsx">@{arr.length }</div>
                <custom-element repeat.for="$value of arr"
                    binded-value01.bind="$value"
                    binded-value02.bind="$value"
                    binded-value03.bind="$value"
                    binded-value04.bind="$value"
                    binded-value05.bind="$value"
                    binded-value06.bind="$value"
                    binded-value07.bind="$value"
                    binded-value08.bind="$value"
                    binded-value09.bind="$value"
                    binded-value10.bind="$value">
                </custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>
                <custom-element repeat.for="$value of obj.arr"></custom-element>

            </div>
        `;
    }
    public reverse() {
        this.arr.reverse();
    }

    public clear() {
        this.arr = [];
    }
}

@customElement('custom-element')
export class CustomElement {

    @bindable() public bindedValue01: string;
    @bindable() public bindedValue02: string;
    @bindable() public bindedValue03: string;
    @bindable() public bindedValue04: string;
    @bindable() public bindedValue05: string;
    @bindable() public bindedValue06: string;
    @bindable() public bindedValue07: string;
    @bindable() public bindedValue08: string;
    @bindable() public bindedValue09: string;
    @bindable() public bindedValue10: string;

    public bindedValue10Changed(newValue: any, oldValue: any) {
        // console.log(newValue, oldValue);
        dummyArrayNew.push(newValue);
        dummyArrayOld.push(oldValue);

    }

    public loadTemplate() {
        return template`<div class="element">@{bindedValue10}</div>`;
    }
}

describe('bindale01 test', () => {


    beforeAll(() => {
        const window = new JSDOM('').window;
        DOM.setConfig(window, window.document);
        configure(App).then((mf: any) => {
            mf.start(DOM.document.body);
        });

    });



    it('bindable caluechanged 01', async () => {

        const input = DOM.document.getElementsByClassName('element');
        expect(input.length).toBe(200);
        expect((input[0] as any).innerHTML).toBe('1');
        expect(dummyArrayNew.join('')).toBe('12345678910');
        expect(dummyArrayOld.join('')).toBe('');
    });

    it('bindable caluechanged 02', async () => {
        const button = DOM.document.getElementsByClassName('button01');
        const event = new (DOM.window as any).CustomEvent('click');
        dummyArrayNew = [];
        dummyArrayOld = [];
        (button[0]).dispatchEvent(event);
        await DOM.waitFor(50);
        const input = DOM.document.getElementsByClassName('element');
        expect(input.length).toBe(200);
        expect((input[0] as any).innerHTML).toBe('10');
        expect(dummyArrayNew.join('')).toBe('10987654321');
        expect(dummyArrayOld.join('')).toBe('12345678910');
    });

    it('bindable caluechanged 03', async () => {
        const button = DOM.document.getElementsByClassName('button01');
        const event = new (DOM.window as any).CustomEvent('click');
        dummyArrayNew = [];
        dummyArrayOld = [];
        (button[0]).dispatchEvent(event);
        await DOM.waitFor(50);

        const input = DOM.document.getElementsByClassName('element');
        const lengths = DOM.document.getElementsByClassName('lengths');
        expect((lengths[0] as any).innerHTML).toBe('20');
        expect(input.length).toBe(200);
        expect((input[0] as any).innerHTML).toBe('1');
        expect(dummyArrayOld.join('')).toBe('10987654321');
        expect(dummyArrayNew.join('')).toBe('12345678910');
    });


    it('bindable caluechanged 04 clear', async () => {
        const button = DOM.document.getElementsByClassName('button02');
        const event = new (DOM.window as any).CustomEvent('click');
        dummyArrayNew = [];
        dummyArrayOld = [];
        (button[0]).dispatchEvent(event);
        await DOM.waitFor(50);

        const lengths = DOM.document.getElementsByClassName('lengths');
        expect((lengths[0] as any).innerHTML).toBe('10');
        const input = DOM.document.getElementsByClassName('element');
        expect(input.length).toBe(100);
        expect(dummyArrayOld.join('')).toBe('');
        expect(dummyArrayNew.join('')).toBe('');
    });



});
