declare module 'bimplus-websdk' {

    export type HTML = string;
    export type Guid = string;
    export type ProjectId = Guid;
    export type ModelId = Guid;
    export type LayerId = Guid;
    export type DivisionTopologyId = Guid;
    export type RevisionId = string;
    export type VisualObjectId = string;

    export type TeamSlug = string;
    export type AccessToken = string;
    export type AccessTokenType = string;

    export function createDefaultConfig(env?: string): ApiConfig;

    export interface ApiConfig {
        protocol: string;
        host: string;
        version?: string;
        cache?: boolean;
    }

    export interface AuthorizeData {
        access_token: string;
    }

    export class Authorize {
        constructor(api: Api);

        // Define methods and properties of the Teams class here

        post(username: string, password: string, applicationId: string): Promise<AuthorizeData>;
    }

    export interface TeamData {
        slug: string;
        id: string;
        name: string;
    }

    export interface Subscription {
        settingName?: string;
        expirationDate?: string;
        id?: string;
        teamId?: string;
        value?: string;
        status?: string;
    }

    export class Teams {
        constructor(api: Api);

        slug: string;

        // Define methods and properties of the Teams class here

        get(teamId?: string, filterEmpty?: boolean): Promise<TeamData[]>;
        getAccountSettings(teamId?: string): Promise<Array<Subscription>>;
    }

    export interface UserData {
        id: string;
        name: string;
        preferedLanguage: string;
    }

    export class User {
        constructor(api: Api);

        // Define methods and properties of the Teams class here

        get(token: AccessToken | null): Promise<UserData>;
        put(userdata: string): Promise<UserData>;
        getSubscriptions(): Promise<Array<Subscription>>;
    }

    type AdditionalParams = {
        [key: string]: string; // This allows key-value pairs as in json string
    }

    export interface Project {
        id: ProjectId;
        name: string;
        teamSlug: TeamSlug;
        teamName: string | undefined;
        rights: object;
    }

    export class Projects {
        constructor(api: Api);
        get(id?: ProjectId, noDisciplines?: boolean, teamSlug?: TeamSlug, alsoRecycleBin?: boolean, additionalParams?: AdditionalParams): Promise<Project | Project[]>;
    }

    export interface ConnexisData {
        projectId: ProjectId,
        modelId: ModelId,
        elements: Guid[];
        settings: {
            connectionMethod: string;
            createRevision?: boolean;
            designCode: string;
            replace: string;
        }
    }

    export interface Sds2ConnexisData {
        SDS2: ConnexisData;
    }
    // export interface IdeaStaticaConnexisData {
    //     IdeaStatica: ConnexisData;
    // }

    export class Connexis {
        constructor(api: Api);
        post(data: Sds2ConnexisData /* | IdeaStaticaConnexisData */) : Promise<void>;
    }

    export interface ObjectFilter {
        id?: string
        module: string
        category: string
        disciplineID: string
        name: string
        filterString: string
        isDefault: boolean
        disableSortByModels: boolean
        readableValues?: Record<string, string>
    }

    export type ObjectFiltersResponse = Array<ObjectFilter>;

    export class ObjectFilters {
        constructor(api: Api);
        get(layerId: Guid | undefined, projectId: Guid | undefined): Promise<ObjectFiltersResponse>
        getSelectionFilteredObjects(selectionId: Guid, filterId: Guid, properties: boolean | undefined, topology: boolean | undefined): Promise<ObjectFilterStructureResponse>
        post(data: string, projectId: string): Promise<ObjectFilter>;
        delete(id: string) : void;
    }

    export interface ObjectsTopologyNode { }

    export interface ObjectTopologyResponse {
        id: string;
        children?: ObjectsTopologyNode[];
        ifcType?: string;
        ifcId?: string;
        elementTypeId?: string;
        isChild?: boolean;
        parent: string;
        name: string;
        type: string;
        layerid?: string;
        number: number;
        level: number;
    }

    export type ObjectComplexPropertyTopologyResponse = ObjectTopologyResponse;

    interface Hyperlink {
        id: string;
        objectId: string;
        orderNumber: number;
        name: string;
        url: string;
    }

    export interface Attachment {
        id: string;
        fileName: string;
        size: number;
    }

    export type Rights = {
        update: boolean;
        share: boolean;
        delete: boolean;
        download: boolean;
    }

    export type GetAttachmentResponse = {
        id: string;
        objectIds: string[];
        name: string;
        fileName: string;
        type: string;
        size: number;
        createdAt: string;
        changed: string;
        changedFile: string;
        changedBy: ChangedBy;
        hash: string;
        attachmentType: string;
        classification: string;
        tag: string;
        sizeMB: string;
        version: number;
        relatedId: string;
        rights: Rights;
        release: boolean;
    }

    type HyperlinksResponse = Hyperlink[];
    type AttachmentLinksResponse = AttachmentLink[];
    type AttachmentResponse = Attachment[];

    export type PostAttachmentResponse = {
        id: string;
        objectIds: string[];
        name: string;
        fileName: string;
        type: string;
        size: number;
        createdAt: string,
        creator: Author;
        changedFile: string,
        hash: string,
        attachmentType: string;
        classification: string;
        tag: string;
        sizeMB: string;
        version: number;
        relatedId: string;
        release: boolean;
    }

    type CommentsResponse = CommentResponse[];

    export interface CommentResponse {
        id: string;
        issueId?: string;
        status?: string | null;
        verbalStatus?: string | null;
        parentId?: string;
        text?: string;
        createdAt?: string;
        modifiedAt?: string;
        author?: Author;
        hyperlinks?: Hyperlink[];
        attachments?: Attachment[];
        attachmentLinks?: AttachmentLink[];
    }

    export interface Author {
        id?: string;
        email?: string;
        status?: string | null;
        firstname?: string;
        lastname?: string;
        company?: string;
        fullname?: string;
        displayname?: string;
        shortdisplayname?: string;
        preferedLanguage?: string | null;
        updated?: string;
        tokensInvalidated?: string;
    }

    export interface Attachment {
        id: string;
        objectIds: string[];
        name: string;
        fileName: string;
        type: string;
        size: number;
        createdAt: string;
        creator: Author;
        changed: string;
        changedFile: string;
        changedBy: ChangedBy;
        attachmentType: string;
        sizeMB: string;
        version: number;
        relatedId: string;
        release: boolean;
        recycleBin: boolean;
    }

    export interface ChangedBy {
        id: string;
        email: string;
        firstname: string;
        lastname: string;
    }

    export interface ObjectData {
        id: string;
        elementtyp?: string;
        type?: string;
        layerid?: string;
        attributes?: Attributes;
        parent?: string;
        localizedAttributeGroups?: LocalizedAttributeGroups;
        [key: string]: unknown;
    }

    export interface LocalizedAttributeGroups {
        [key: string]: unknown;
    }

    export interface Attributes {
        [key: string]: unknown;
        slide?: Slide;
    }

    export interface Slide {
        scene: Scene | SceneResponse;
    }

    export interface Scene {
        viewMode?: string;
        thumbnail?: string;
        viewBox?: ViewBox;
        camera?: Camera;
        objects?: SceneObjects;
        rotationCenter?: number[];
        version?: [number, number, number]; // Tuple type for version (major, minor, patch)
        topology?: Topology[];
        layers?: SelectionObjectLayer[];
        [key: string]: unknown;
    }

    export type SceneResponse = string;

    export interface Camera {
        [key: string]: unknown;
    }

    export interface Topology {
        id: string;
        divisionTopologyId: string;
        visible: boolean;
        revision: number;
        [key: string]: unknown;
    }

    export interface SceneObjects {
        selected?: string[];
        coloring?: Coloring;
        selectedInfo?: SelectedInfo[];
    }

    export interface SelectedObject {
        id: string;
        node: string;
        revision: number;
    }

    export class Objects {
        constructor(api: Api);
        get(objectId: string, revision: number | undefined, properties: string | undefined, projectId: string | undefined, shortInfo: boolean | undefined, type: string | undefined): Promise<ObjectProperties>;
        getTopology(objectId: string, revision: number | undefined, hideElements: boolean, shortInfo: boolean, batch: string | undefined): Promise<ObjectTopologyResponse>;
        getComplexPropertiesTopology(objectId: string, revision: number | undefined): Promise<ObjectComplexPropertyTopologyResponse>;
        getHyperlinks(objectId: string): Promise<HyperlinksResponse>;
        postHyperlink(objectId: string, data: string): Promise<Hyperlink>;
        getAttachmentLinks(objectId: string): Promise<AttachmentLinksResponse>;
        postAttachmentLink(objectId: string, data: string): Promise<AttachmentLink>;
        deleteAttachmentLink(objectId: string,AttachmentLinkId:string): Promise<void>;
        postComment(objectId: string, data: string): Promise<CommentResponse>;
        getComments(objectId: string): Promise<CommentsResponse>;
        postAttachment(objectId: string, data: FormData, uploadProgress?: () => void, documentFolderId?: string): Promise<PostAttachmentResponse>;
        getAttachments(objectId: string): Promise<AttachmentResponse>;
        put(objectId: string, data: string, projectId?: string): Promise<ObjectData>;
        getInternal(objectId: string, revision?: number): Promise<ObjectData>;
    }

    export class Attachments {
        constructor(api: Api);
        delete(id:string, version?: number): Promise<void>;
        get(id: string): Promise<GetAttachmentResponse>;
    }

    export interface SelectionObjectTopologyNode {
        id: string;
        visible: boolean;
        opaque: boolean;
        opacity: number;
    }

    export interface SelectionObjectLayer {
        revision: number;
        id: string;
        name?: string;
        divisionId: string;
        divisionName?: string;
        visible?: boolean;
        opaque?: boolean;
        opacity?: number;
        valid?: boolean;
        divisionTopologyId?: string;
        revisions?: Array<number>;
        [key: string]: unknown;
    }

    export interface SelectionObjectTopology {
        topology: SelectionObjectTopologyNode[];
        layers: SelectionObjectLayer[];
    }

    export interface SelectionObjectTopologyStructure {
        layers: SelectionObjectLayer[];
        structures: Topology[] | string[];
    }

    export interface SelectionObject {
        id?: string;
        projectid: string;
        divisionid?: string;
        singleuse: boolean;
        revisionnr?: string;
        type: string;
        elements?: string[];
        revisionelements?: string[];
        filter?: string;
        topology?: SelectionObjectTopology;
        topologyStructure?: SelectionObjectTopologyStructure
    }

    export interface ExportObject {
        description: string;
        id?: string;
        name: string;
        projectId: string;
        singleUse: boolean;
        selection: SelectionObject;
        [key: string]: unknown;
    }

    export class ExportService {
        constructor(api: Api);
        createExportSelection(projectId: Guid, data: string): Promise<ExportObject>;
    }

    export interface StructureNode {
        id: string;
        parent?: string;
        name: string;
        type: string;
        children?: StructureNode[];
        lastTopologyId?: string;
        count: number;
        level: number;
        nodeInfo: string;
        hasGeometry?: boolean;
    }

    export interface ObjectFilterStructureResponse {
        structure: StructureNode;
        structureDepth: number;
    }

    export class PrivacyTexts {
        constructor(api: Api);
        get(lang: string | undefined, type: string | undefined): Promise<HTML>;
    }

    export interface IDBCache {
        data: string;

        clear(): void;
    }

    export class Hyperlinks {
        constructor(api: Api);
        delete(id: string): Promise<void>;
    }

    export class AttachmentLink {
        id: string;
        name: string;
        fileName:string
        size:number;
        link:string;
        version:number;
        fileNameShort:string;
        extension:string;
        objectIds:string[];
        sizeMB: string
      }

    export class Comments {
        constructor(api: Api);
        delete(id: string): Promise<void>;
    }

    export interface Coloring {
    }

    export interface SelectedInfo {
    }

    export interface ViewBox {
    }

    export interface ObjectProperties {
    }

    export class Api {
        constructor(config: ApiConfig);

        // Define methods and properties of the Teams class here

        authorize: Authorize;
        teams: Teams;
        user: User;
        projects: Projects;
        connexis: Connexis;
        objectFilters: ObjectFilters;
        objects: Objects;
        attachments: Attachments;
        exportService: ExportService;
        terms: PrivacyTexts;
        imprints: PrivacyTexts;
        dataProtection: PrivacyTexts;
        hyperlinks: Hyperlinks;
        comments: Comments;

        setAccessToken(token: AccessToken): void;
        getAccessToken(): AccessToken | null;

        setTokenType(tokenType: AccessTokenType): void;
        getTokenType(): AccessTokenType | null;

        setAccessTokenAndType(token: AccessToken, tokenType: AccessTokenType): void;
        getAccessTokenAndType(): { token: AccessToken | null, tokenType: AccessTokenType | null }

        setTeamSlug(slug: TeamSlug): void;
        getCache(): IDBCache;
        getApiTeamUrl(): string;
    }
}
