import { makePropDecorator } from '../../google-decorator-factories';
import { Type } from '@angular/core';
import { BindDecorator } from '../bind.decorator';
import { ReflectiveModelBinderFactory, ReflectiveQueryMatcherFactory } from '../../services';

export interface BindEntityDecorator {
    <T>(queryType: Type<T>, optional?: boolean): any;
    new <T>(queryType: Type<T>, optional?: boolean): any;
}

export const Entity: BindEntityDecorator = makePropDecorator('BindEntity', <T>(queryType: Type<T>, optional = false) => {
    return ({
        binding: {
            priority: 1,
            bind: (({ entities = [] }, fieldName, injector) => {
                const modelBinderProvider = injector.get(ReflectiveModelBinderFactory);
                const queryMatcherFactory = injector.get(ReflectiveQueryMatcherFactory);

                const modelBinder = modelBinderProvider.make(queryType);
                const queryMatcher = queryMatcherFactory.make(queryType);
                const matchingEntitity = entities.find(hypermedia => queryMatcher.matches(hypermedia));
                if (!matchingEntitity) {
                    if (optional) {
                        return undefined;
                    }
                    const foundClasses = entities
                        .reduce((acc, { class: classes = [] }) => [...acc, ...classes], []);

                    return null;
                    // throw new Error(`Type query did not find any bindable element of type: ${queryType.name}, the only classes found were: ${noDupesFoundClasses.join(', ')}`);
                }

                return modelBinder.bind(matchingEntitity);
            })
        } as BindDecorator
    }) as any;
});
