"use strict";

import {expect} from "chai"
import {equipWithInternal} from "../../../source/types/internal.mjs";
import {Observer} from "../../../source/types/observer.mjs";

class SomeRandomClass1 extends Object {

    doit() {
        return "done";
    }
}

class SomeRandomClass2 extends Object {

    constructor() {
        super();
        equipWithInternal.call(this);
    }

    get defaultInternal() {
        return {
            test: "test"
        }
    }

}

describe('Base inject with options', function () {

    describe('new SomeRandomClass', function () {

        it('is instance of SomeRandomClass1', function () {
            expect(new SomeRandomClass2).not.to.be.instanceOf(SomeRandomClass1);
            expect(new SomeRandomClass2).to.be.instanceOf(SomeRandomClass2);
        });

        it('is instance of SomeRandomClass2', function () {
            expect(new SomeRandomClass1).to.be.instanceOf(SomeRandomClass1);
            expect(new SomeRandomClass1).not.to.be.instanceOf(SomeRandomClass2);
        });

    })

    describe('Extends SomeRandomClass with internals', function () {

        it('attach and notify internal observer', function (done) {
            const c = new SomeRandomClass2;
            c.attachInternalObserver(new Observer(() => {
                done();
            }));

            c.setInternal("test", "test");

        });

        it('attach and remove internal observer', function () {
            const c = new SomeRandomClass2;


            const observer = new Observer(() => {

            });

            expect(c.containsInternalObserver(observer)).to.be.false;
            c.attachInternalObserver(observer);
            expect(c.containsInternalObserver(observer)).to.be.true;
            c.detachInternalObserver(observer);
            expect(c.containsInternalObserver(observer)).to.be.false;

        });

        it("getInternal and setInternal", function () {
            const c = new SomeRandomClass2;
            expect(c.setInternal("test", "yeah")).to.be.instanceOf(SomeRandomClass2);
            expect(c.getInternal("test")).to.be.equal("yeah");
        });

        it("deal with default values", function () {
            const testClass = class extends Object {
                constructor() {
                    super();
                    equipWithInternal.call(this);
                }

                get internalDefaults() {
                    return {
                        test: "xyz"
                    }
                }
            }


            const c = new testClass;
            expect(c.getInternal("test")).to.be.equal("xyz");
            expect(c.getInternal("test2", "abc")).to.be.equal("abc");
        });

        it("deal with defaults from defaults", function () {
            const testClass = class extends Object {
                constructor() {
                    super();
                    equipWithInternal.call(this);
                }

                get internalDefaults() {
                    return {
                        test: "xyz"
                    }
                }
            }

            const testClass2 = class extends testClass {
                constructor() {
                    super();
                    equipWithInternal.call(this);
                }

                get internalDefaults() {
                    return Object.assign({}, super.internalDefaults, {
                        test2: "abc"
                    })
                }
            }

            const c = new testClass2;
            expect(c.getInternal("test")).to.be.equal("xyz");
            expect(c.getInternal("test2")).to.be.equal("abc");
        });
        
        it("set multiple values", function () {
            const c = new SomeRandomClass2;
            expect(c.setInternals({
                test: "yeah",
                test2: "yeah2"
            })).to.be.instanceOf(SomeRandomClass2);
            expect(c.getInternal("test")).to.be.equal("yeah");
            expect(c.getInternal("test2")).to.be.equal("yeah2");
            
            c.setInternals({
                test2: "yeah2-new",
                test3: "yeah3"
            });
            
            expect(c.getInternal("test")).to.be.equal("yeah");
            expect(c.getInternal("test2")).to.be.equal("yeah2-new");
            expect(c.getInternal("test3")).to.be.equal("yeah3");
        });

    });


})