import { getMetadataStorage } from "../utils/metadata-storage";
import { FieldType, FieldTypes } from "../types/field";
import { FieldOptions } from "../options/field-options";
import { OdooFieldMetadata } from "../metadata/field-metadata";

/**
 *
 */
export function OdooField(): Function;

/**
 *
 */
export function OdooField(type: FieldType): Function;

/**
 *
 */
export function OdooField(options: FieldOptions): Function;

/**
 *
 */
export function OdooField(type: FieldType, options: FieldOptions);

/**
 *
 */
export function OdooField(typeOrOptions?: FieldType|FieldOptions, options?: FieldOptions): Function {

    let type: FieldType | undefined;

    if (typeof typeOrOptions === "string") {
        type = <FieldType>typeOrOptions;

    } else if (typeOrOptions) {
        options = <FieldOptions>typeOrOptions;
        type = typeOrOptions.type;
    }

    return function (object: Object, propertyName: string) {
        if (!type) {
            const typeMetadata = Reflect && (Reflect as any).getMetadata ? (Reflect as any).getMetadata("design:type", object, propertyName) : undefined;
            if (typeMetadata) {
                type = FieldTypes.determineTypeFromFunction(typeMetadata);
            }
        }

        if (!options) {
            options = {} as FieldOptions;
        }

        if (!options.type && type) {
            options = Object.assign({ type: type } as FieldOptions, options);
        }

        if (!options.type) {
            throw new Error("Tipo no definido");
        }

        const args: OdooFieldMetadata = {
            target: object.constructor,
            fieldName: propertyName,
            options: options
        };

        getMetadataStorage().fields.add(args);
    };
}