var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};
import { createElement, Fragment } from "react";
import { SugaredField, HasOne, BindingError, VariableInputTransformer } from "@contember/binding";
import { resolveAcceptingSingleKind } from "./utils/resolveAccept.js";
import { resolveAllAcceptedMimes } from "./utils/resolveAllAcceptedMimes.js";
import { disconnectAtBase } from "./utils/disconnectAtBase.js";
import { staticRenderFileKind } from "./utils/staticRenderFileKind.js";
import { AcceptFileKindError } from "./AcceptFileKindError.js";
class DiscriminatedFileHandler {
  constructor(discriminationField, baseEntity, fileKinds) {
    __publicField(this, "hasBaseEntity");
    __publicField(this, "acceptedMimes");
    this.discriminationField = discriminationField;
    this.baseEntity = baseEntity;
    this.fileKinds = fileKinds;
    this.hasBaseEntity = this.baseEntity !== void 0;
    this.acceptedMimes = resolveAllAcceptedMimes(Array.from(fileKinds.values(), (it) => it.datum.acceptMimeTypes).flat());
  }
  async acceptFile(fileOptions) {
    const errors = [];
    for (const { datum: fileKind, discriminateBy } of this.fileKinds.values()) {
      try {
        const result = await resolveAcceptingSingleKind(fileOptions, fileKind);
        if (result !== void 0) {
          return {
            fileKind,
            finalizeEntity: (entity) => {
              DiscriminatedFileHandler.fillDiscriminateBy(entity, this.baseEntity, discriminateBy, this.discriminationField);
            }
          };
        }
      } catch (e) {
        if (e instanceof AcceptFileKindError) {
          errors.push(e);
        }
      }
    }
    if (errors.length) {
      throw new AggregateError(errors);
    } else {
      return void 0;
    }
  }
  resolveEntity(parentEntity) {
    const containingEntity = this.getContainingEntity(parentEntity);
    const fileKind = this.resolveFileKind(parentEntity);
    if (!fileKind) {
      return {
        parentEntity,
        isEmpty: true,
        fileEntity: void 0,
        fileKind: void 0,
        getErrorHolders: () => {
          return [
            parentEntity,
            ...parentEntity == containingEntity ? [containingEntity] : []
          ];
        }
      };
    }
    const fileEntity = fileKind.baseEntity ? containingEntity.getEntity(fileKind.baseEntity) : containingEntity;
    const baseEntity = this.baseEntity;
    return {
      parentEntity,
      isEmpty: false,
      fileEntity,
      fileKind,
      destroy: baseEntity ? () => {
        disconnectAtBase(baseEntity, parentEntity);
      } : void 0,
      getErrorHolders: () => {
        return [
          parentEntity,
          ...containingEntity !== parentEntity ? [containingEntity] : [],
          ...fileEntity !== containingEntity ? [fileEntity] : [],
          ...fileKind.extractors.flatMap((it) => it.getErrorsHolders?.({
            entity: fileEntity,
            environment: fileEntity.environment
          }) ?? [])
        ];
      }
    };
  }
  staticRender(environment) {
    const staticKinds = Array.from(this.fileKinds.values(), (fileKind) => staticRenderFileKind(fileKind.datum, environment));
    const childrenOutsideBase = /* @__PURE__ */ createElement(Fragment, null, staticKinds.map(([, it], index) => /* @__PURE__ */ createElement(Fragment, {
      key: index
    }, it)));
    const children = /* @__PURE__ */ createElement(Fragment, null, /* @__PURE__ */ createElement(SugaredField, {
      field: this.discriminationField,
      isNonbearing: true
    }), staticKinds.map(([children2], i) => /* @__PURE__ */ createElement(Fragment, {
      key: i
    }, children2)));
    return this.baseEntity === void 0 ? /* @__PURE__ */ createElement(Fragment, null, children, childrenOutsideBase) : /* @__PURE__ */ createElement(Fragment, null, childrenOutsideBase, /* @__PURE__ */ createElement(HasOne, {
      field: this.baseEntity
    }, children));
  }
  resolveFileKind(parent) {
    const containingEntity = this.getContainingEntity(parent);
    const discriminant = containingEntity.getField(this.discriminationField).value;
    if (!discriminant) {
      return void 0;
    }
    const fileKind = this.fileKinds.get(discriminant);
    if (!fileKind) {
      throw new BindingError(`Undefined file kind "${discriminant}".`);
    }
    return fileKind.datum;
  }
  getContainingEntity(accessor) {
    return this.baseEntity ? accessor.getEntity(this.baseEntity) : accessor;
  }
  static fillDiscriminateBy(entity, baseEntity, discriminateBy, discriminationField) {
    if (baseEntity !== void 0) {
      entity = entity.getEntity(baseEntity);
    }
    entity.getField(discriminationField).updateValue(VariableInputTransformer.transformValue(discriminateBy, entity.environment));
  }
}
export { DiscriminatedFileHandler };
//# sourceMappingURL=DiscriminatedFileHandler.js.map
