import { FormlyJsonschema } from "@ngx-formly/core/json-schema";
import { FormlyJsonschemaOptions } from "@ngx-formly/core/json-schema/formly-json-schema.service";
import { FormlyFieldConfig } from "@ngx-formly/core";
import { JSONSchema7 } from 'json-schema';
import { JsonschemasService } from "./jsonschemas.service";
import { Observable, map } from "rxjs";
import { Injectable } from "@angular/core";

@Injectable({
  providedIn: 'root',
})
export class CrudFormlyJsonschemaService extends FormlyJsonschema {
    constructor(private jsonSchemasService: JsonschemasService) {
        super();
    }

    override toFieldConfig(schema: JSONSchema7): FormlyFieldConfig {
        let fieldConfig = super.toFieldConfig(schema, new CrudFormlyJsonschemaOptions());
        return fieldConfig;
    }

    getCreateFields(resourceName: string): Observable<FormlyFieldConfig> {
        resourceName = resourceName.charAt(0).toUpperCase() + resourceName.slice(1);
        return this.jsonSchemasService.getCreateResource(resourceName).pipe(
            map((schemas: any) => this.toFieldConfig(schemas)),
        )
    }

    getUpdateFields(resourceName: string): Observable<FormlyFieldConfig> {
        resourceName = resourceName.charAt(0).toUpperCase() + resourceName.slice(1);
        return this.jsonSchemasService.getUpdateResource(resourceName).pipe(
            map((schemas: any) => this.toFieldConfig(schemas)),
        )
    }
}

export class CrudFormlyJsonschemaOptions implements FormlyJsonschemaOptions {
    map = (field: any, schema: any) => {
        if (schema.hasOwnProperty('foreignKey')) {
            field.type = "foreign-key";
            field.foreignKey = schema['foreignKey'];
        } else if (schema.format === 'date-time') {
            field.type = "datetime";
        } else if (schema.format === 'date') {
            field.type = "date";
        } else if (
            (schema.hasOwnProperty('hidden') && schema.hidden)
            || (schema.hasOwnProperty('enum') && schema.enum.length == 1 && schema.enum[0] == schema.default)
        ) {
            field.type = "hidden";
        } else if (schema.type == "array" && schema.format == "dictionary") {
            field.type = "dictionary";
        } else if (schema.type == "string" && schema.hasOwnProperty('props')
            && schema.props.hasOwnProperty("richtext") && schema.props.richtext) {
            field.type = "richtext";
        } else if (schema.type == "string" && schema.format == "signature-link") {
            field.type = "signature-link";
        } else if (field.type == "enum" && field.props.multiple) {
            field.type = 'multicheckbox';
        }

        if (schema.hasOwnProperty('props')) {
            field.props = {...field.props, ...schema.props}
        }

        return field;
    }
}
