import {ObjectTypeName, PUBLIC_OBJECT_NAME, TEMPLATES_OBJECT_NAME} from '../..';
import {ObjectTreesApplicationInterface} from '../../application.interface';
import {ExtensionProvider} from '../../integration/extension.provider';
import {UtilsCommonProvider} from '../utils-common/utils-common.provider';
import {
  CONTENT_GENERIC_PROVIDER,
  TEMPLATE_CONFIGURATION_HOLDER_TEMPLATE_CONFIGURATION_SUBTYPE,
  TEMPLATE_CONFIGURATION_HOLDER_TYPE,
  TEMPLATE_CONFIGURATION_TYPE,
  TEMPLATE_EMBEDDED_CONFIGURATION_TYPE,
  TEMPLATE_REFERRER_TYPE,
  TEMPLATE_VIEW_TEMPLATE_EMBEDDED_CONFIGURATION_SUBTYPE,
  TEMPLATE_VIEW_TYPE,
} from './content-generic-template.const';
import {
  ContentGenericTemplate,
  ContentGenericTemplateRepository,
  ContentGenericTemplateService,
  GenericTemplate,
} from './content-generic-template.definition';
import {TransientContentGenericService} from './transient-content-generic.service';

export class ContentGenericTemplateProvider extends ExtensionProvider {
  constructor(protected app: ObjectTreesApplicationInterface) {
    super(CONTENT_GENERIC_PROVIDER, app);

    this.requiredProviders.push(UtilsCommonProvider);

    this.models.push(GenericTemplate);
    this.models.push(ContentGenericTemplate);
    this.repositories.push({repoClass: ContentGenericTemplateRepository});

    this.services.push(
      {cls: ContentGenericTemplateService},
      {cls: TransientContentGenericService},
    );

    this.objectTypes.push(
      TEMPLATE_CONFIGURATION_HOLDER_TYPE,
      TEMPLATE_VIEW_TYPE,
      TEMPLATE_CONFIGURATION_TYPE,
      TEMPLATE_EMBEDDED_CONFIGURATION_TYPE,
      TEMPLATE_REFERRER_TYPE,
    );

    this.objectSubTypes.push(
      TEMPLATE_CONFIGURATION_HOLDER_TEMPLATE_CONFIGURATION_SUBTYPE,
      TEMPLATE_VIEW_TEMPLATE_EMBEDDED_CONFIGURATION_SUBTYPE,
    );
  }

  async boot(): Promise<void> {
    for (const typeField of this.appCtx.implementingTypes.value[
      TEMPLATE_VIEW_TYPE.name
    ]) {
      const allTypes = await this.objectTypeService.searchAll();
      await this.addType({
        name: allTypes[typeField].name + 'Configuration',
        inheritedTypesIds: [TEMPLATE_CONFIGURATION_TYPE.name],

        definition: {
          properties: {
            templateObjectTreeId: {
              oneOfTree: [
                {
                  treeType: allTypes[typeField].name,
                },
                {
                  treeType: allTypes[typeField].name,
                  namespaceName: TEMPLATES_OBJECT_NAME,
                  namespaceType: ObjectTypeName.REPOSITORY_CATEGORY,
                  ownerName: PUBLIC_OBJECT_NAME,
                  ownerType: ObjectTypeName.REPOSITORY,
                },
              ],
            },
          },
        },
      });
      await this.addType({
        name: allTypes[typeField].name + 'EmbeddedConfiguration',
        inheritedTypesIds: [
          allTypes[typeField].name + 'Configuration',
          TEMPLATE_EMBEDDED_CONFIGURATION_TYPE.name,
        ],
      });
      await this.addSubType({
        typeName: allTypes[typeField].name,
        subTypeName: allTypes[typeField].name + 'EmbeddedConfiguration',
        name: TEMPLATE_CONFIGURATION_TYPE.name,
        tree: true,
      });
    }
    await super.boot();
  }
}
