class EntityLevel {
  constructor(path: string) {
    this.path = path;
  }

  readonly path: string;
  readonly standardFields: Map<string, Api.SingleTableField> = new Map();
  readonly refFields: Map<string, EntityLevel> = new Map();

  private getRealLevel(level: EntityLevel | undefined) {
    return level || this;
  }

  add(field: Api.SingleTableField) {
    const fullPath = field.code.split('.');
    if (field.valueType.endsWith('.entity') || field.valueType.endsWith('.enum')) {
      fullPath.push('id');
    }
    const etyPath = fullPath.pop();
    if (!!!etyPath) {
      return;
    }
    let currentLevel: EntityLevel | undefined;
    fullPath.forEach((p) => {
      let levelVar = this.getRealLevel(currentLevel)?.refFields.get(p);
      if (!!!levelVar) {
        levelVar = new EntityLevel(p);
        this.getRealLevel(currentLevel).refFields.set(p, levelVar);
      }
      currentLevel = levelVar;
    });
    this.getRealLevel(currentLevel).standardFields.set(etyPath, field);
  }
}

class RequistFieldBuilderManager {
  build(singleTable: Api.SingleTable, rootPath = 'content') {
    const rootLevel = this.toEntityLevel(singleTable, rootPath);
    return this.buildEntityLevel(rootLevel);
  }

  private toEntityLevel(singleTable: Api.SingleTable, rootPath: string) {
    const entityLevel = new EntityLevel(rootPath);
    singleTable.fields.forEach((f) => entityLevel.add(f));
    return entityLevel;
  }

  private buildEntityLevel(entityLevel: EntityLevel) {
    const specification: string[] = [];
    entityLevel.standardFields.forEach((field, ptyName) => {
      specification.push(ptyName);
    });
    if (specification.filter((f) => f === 'id').length <= 0) {
      specification.push('id');
    }
    entityLevel.refFields.forEach((el) => {
      specification.push(this.buildEntityLevel(el));
    });
    if (entityLevel.path.length > 0) {
      return `${entityLevel.path}{${specification.join(',')}}`;
    }
    return `{${specification.join(',')}}`;
  }
}

const requistFieldBuilderManager = new RequistFieldBuilderManager();
export default requistFieldBuilderManager;
