/* eslint max-classes-per-file: ["error", 20] */
import { describe, it } from "mocha";
import { Container } from "../Container";
import { ContainerBuilder } from "../ContainerBuilder";
import { ContainerServices, DepsMap, IContainerBuilder, Refs, Resolver } from "../interfaces";
import { fluent } from "../traits";

class Foo {
    foo = "foo";
}

class Bar {
    bar = "bar";

    constructor(foo?: () => Foo) { }
}

interface Services {
    foo: Foo;

    bar?: Bar;

    baz: Foo;

    box?: Foo;

    //container: string;
}

interface ServicesB {
    // will give errors
    // baz: Bar;

    baz: Foo;

    zoo?: Foo;
}

declare const resolver: Resolver<Services>;

const foo = resolver("foo", { lazy: true, default: null });

const mmap = <X extends DepsMap<Services>>(m: X) => { };

declare const refs: Refs<Services>;

if (refs && refs.name === "foo") {
    refs.default;
}

declare const x: ContainerServices<Services>;

x.container.resolve("container");


mmap({
    fooz: { name: "foo", lazy: false, default: undefined },
    ooz: "bar"
});

interface SharedServices {
    foo: Foo;

    bar?: Bar;

    baz: Bar;
}

const config = fluent<Services>()
    .declare<ServicesB>()
    .register({
        zoo: it => it.value(new Foo()),
        bar: it => it
            .lifetime("context") // тип активации, время жизни
            .wants({
                self: "container",
                childContainer: "childContainer",
                bar: "bar",
                foo$: { name: "foo", lazy: true } // отложенная активация, фабричный метод
            })
            .override({ // переопределение сервиса
                box: it => it.factory(() => new Foo())
                
            })
            .factory(({ foo$, bar, self, childContainer }) => // фабрика получает объект с именованными зависимостями
                new Bar(foo$) // создается экземпляр сервиса
            ),
        foo: it => it.factory(() => new Foo()),
        baz: it => it.value(new Foo()),
        //box: it => it.factory(() => new Foo())
    })
    .done();

declare const container: IContainerBuilder<ContainerServices<Services>, keyof Services>;

const v = container.build().resolve("foo");
if (v) {
    // noop
}

const c2 = config.configure(container);

c2.resolve("foo");

declare const m: ContainerServices<{ foo?: Foo }>["container"];

m.resolve("container").resolve("container").resolve("foo");