import { BimChangeStatus } from './BimChangeStatus';
import { BimChangeMetadataQuery } from './BimChangeMetadataQuery';
import { BimChangeIfc, BimChangeDwg, BimChangeLayer, BimChangeBlob, BimChange, BimFolder } from './bim-api-client';
import { BimChangeUploadable } from './client/UploadApiClient';

/**
 * Predefined queries to use with {@link BimCoreApiClient.getChanges}.
 */
export class PredefinedBimChangeMetadataQuery {
    /**
     * Gets all successfully processed folders.
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.folder())
     * ```
     * Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static folder(): BimChangeMetadataQuery<BimFolder> {
        return { query: `folder.status=${BimChangeStatus.Processed}` };
    }

    /**
     * Gets all successfully processed folders.
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.folder())
     * ```
     * Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static all(): BimChangeMetadataQuery<BimChange> {
        return { query: 'all' };
    }

    /**
     * Gets all successfully processed IFC changes.
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.ifc())
     * ```
     * @param status Status of IFC files to get.
     * Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static ifc(status: BimChangeStatus = BimChangeStatus.Processed): BimChangeMetadataQuery<BimChangeIfc> {
        return PredefinedBimChangeMetadataQuery.blob<BimChangeIfc>('ifc', status);
    }

    /**
     * Gets all successfully processed DWG changes.
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.dwg())
     * ```
     * @param status Status of DWG files to get.
     * Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static dwg(status: BimChangeStatus = BimChangeStatus.Processed): BimChangeMetadataQuery<BimChangeDwg> {
        return PredefinedBimChangeMetadataQuery.blob<BimChangeDwg>('dwg', status);
    }

    /**
     * Gets all successfully processed PDF changes.
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.pdf())
     * ```
     * @param status Status of PDF files to get.
     * Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static pdf(status: BimChangeStatus = BimChangeStatus.Processed): BimChangeMetadataQuery<BimChangeBlob> {
        return PredefinedBimChangeMetadataQuery.blob<BimChangeBlob>('pdf', status);
    }

    /**
     * Gets all layers of a specific format
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.layer("sensors"))
     * ```
     * @param format Type of layer to get. For example "sensors"
     * @returns Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static layer(format: string): BimChangeMetadataQuery<BimChangeLayer> {
        return { query: `_system.layers.format=${format}` };
    }

    /**
     * Retrieves the BimChangeMetadataQuery for layer attachments.
     * @param format The format or layerId property.
     * @returns The BimChangeMetadataQuery object.
     * @example
     * ```
     * // Get all layer attachments for sensor layers in projectA
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.layerAttachments("sensors"));
     * // Get all layer attachments for sensor layers in folderA
     * api.getChanges(folderA, PredefinedBimChangeMetadataQuery.layerAttachments("sensors"));
     * ```
     */
    public static layerAttachments<T extends BimChangeUploadable = BimChangeUploadable>(
        format: string
    ): BimChangeMetadataQuery<T> {
        return { query: `_system.attachment.parent.format=${format}` };
    }

    /**
     * Gets all blobs/files with a specific file extension and status
     * @example
     * ```
     * api.getChanges(projectA, PredefinedBimChangeMetadataQuery.blob("docx"))
     * ```
     * @param extension File extension
     * @param status Status of files to get.
     * @returns Query for use with {@link TwinfinityApiClient.getChanges}.
     */
    public static blob<T extends BimChange = BimChangeBlob>(
        extension: string,
        status: BimChangeStatus = BimChangeStatus.Processed
    ): BimChangeMetadataQuery<T> {
        return { query: `${extension}.status=${status}` };
    }
}
