"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssetStackResponseDto = exports.AssetResponseDto = exports.SanitizedAssetResponseDto = void 0;
exports.mapAsset = mapAsset;
const openapi = require("@nestjs/swagger");
const swagger_1 = require("@nestjs/swagger");
const decorators_1 = require("../decorators");
const exif_dto_1 = require("./exif.dto");
const person_dto_1 = require("./person.dto");
const tag_dto_1 = require("./tag.dto");
const user_dto_1 = require("./user.dto");
const enum_1 = require("../enum");
const asset_util_1 = require("../utils/asset.util");
const bytes_1 = require("../utils/bytes");
const date_1 = require("../utils/date");
const mime_types_1 = require("../utils/mime-types");
const validation_1 = require("../validation");
class SanitizedAssetResponseDto {
    id;
    type;
    thumbhash;
    originalMimeType;
    localDateTime;
    duration;
    livePhotoVideoId;
    hasMetadata;
    width;
    height;
    static _OPENAPI_METADATA_FACTORY() {
        return { id: { required: true, type: () => String }, type: { required: true, enum: require("../enum").AssetType }, thumbhash: { required: true, type: () => String, nullable: true }, originalMimeType: { required: false, type: () => String }, localDateTime: { required: true, type: () => String }, duration: { required: true, type: () => String }, livePhotoVideoId: { required: false, type: () => String, nullable: true }, hasMetadata: { required: true, type: () => Boolean }, width: { required: true, type: () => Number, nullable: true }, height: { required: true, type: () => Number, nullable: true } };
    }
}
exports.SanitizedAssetResponseDto = SanitizedAssetResponseDto;
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Asset ID' }),
    __metadata("design:type", String)
], SanitizedAssetResponseDto.prototype, "id", void 0);
__decorate([
    (0, validation_1.ValidateEnum)({ enum: enum_1.AssetType, name: 'AssetTypeEnum', description: 'Asset type' }),
    __metadata("design:type", String)
], SanitizedAssetResponseDto.prototype, "type", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({
        description: 'Thumbhash for thumbnail generation (base64) also used as the c query param for thumbnail cache busting.',
    }),
    __metadata("design:type", Object)
], SanitizedAssetResponseDto.prototype, "thumbhash", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: 'Original MIME type' }),
    __metadata("design:type", String)
], SanitizedAssetResponseDto.prototype, "originalMimeType", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({
        type: 'string',
        format: 'date-time',
        description: 'The local date and time when the photo/video was taken, derived from EXIF metadata. This represents the photographer\'s local time regardless of timezone, stored as a timezone-agnostic timestamp. Used for timeline grouping by "local" days and months.',
        example: '2024-01-15T14:30:00.000Z',
    }),
    __metadata("design:type", String)
], SanitizedAssetResponseDto.prototype, "localDateTime", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Video duration (for videos)' }),
    __metadata("design:type", String)
], SanitizedAssetResponseDto.prototype, "duration", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: 'Live photo video ID' }),
    __metadata("design:type", Object)
], SanitizedAssetResponseDto.prototype, "livePhotoVideoId", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Whether asset has metadata' }),
    __metadata("design:type", Boolean)
], SanitizedAssetResponseDto.prototype, "hasMetadata", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Asset width' }),
    __metadata("design:type", Object)
], SanitizedAssetResponseDto.prototype, "width", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Asset height' }),
    __metadata("design:type", Object)
], SanitizedAssetResponseDto.prototype, "height", void 0);
class AssetResponseDto extends SanitizedAssetResponseDto {
    createdAt;
    deviceAssetId;
    deviceId;
    ownerId;
    owner;
    libraryId;
    originalPath;
    originalFileName;
    fileCreatedAt;
    fileModifiedAt;
    updatedAt;
    isFavorite;
    isArchived;
    isTrashed;
    isOffline;
    visibility;
    exifInfo;
    tags;
    people;
    unassignedFaces;
    checksum;
    stack;
    duplicateId;
    resized;
    isEdited;
    static _OPENAPI_METADATA_FACTORY() {
        return { createdAt: { required: true, type: () => String }, deviceAssetId: { required: true, type: () => String }, deviceId: { required: true, type: () => String }, ownerId: { required: true, type: () => String }, owner: { required: false, type: () => require("./user.dto").UserResponseDto }, libraryId: { required: false, type: () => String, nullable: true }, originalPath: { required: true, type: () => String }, originalFileName: { required: true, type: () => String }, fileCreatedAt: { required: true, type: () => String }, fileModifiedAt: { required: true, type: () => String }, updatedAt: { required: true, type: () => String }, isFavorite: { required: true, type: () => Boolean }, isArchived: { required: true, type: () => Boolean }, isTrashed: { required: true, type: () => Boolean }, isOffline: { required: true, type: () => Boolean }, visibility: { required: true, enum: require("../enum").AssetVisibility }, exifInfo: { required: false, type: () => require("./exif.dto").ExifResponseDto }, tags: { required: false, type: () => [require("./tag.dto").TagResponseDto] }, people: { required: false, type: () => [require("./person.dto").PersonWithFacesResponseDto] }, unassignedFaces: { required: false, type: () => [require("./person.dto").AssetFaceWithoutPersonResponseDto] }, checksum: { required: true, type: () => String }, stack: { required: false, type: () => require("./asset-response.dto").AssetStackResponseDto, nullable: true }, duplicateId: { required: false, type: () => String, nullable: true }, resized: { required: false, type: () => Boolean }, isEdited: { required: true, type: () => Boolean } };
    }
}
exports.AssetResponseDto = AssetResponseDto;
__decorate([
    (0, swagger_1.ApiProperty)({
        type: 'string',
        format: 'date-time',
        description: 'The UTC timestamp when the asset was originally uploaded to Immich.',
        example: '2024-01-15T20:30:00.000Z',
    }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "createdAt", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Device asset ID' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "deviceAssetId", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Device ID' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "deviceId", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Owner user ID' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "ownerId", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: undefined }),
    __metadata("design:type", user_dto_1.UserResponseDto)
], AssetResponseDto.prototype, "owner", void 0);
__decorate([
    (0, validation_1.ValidateUUID)({
        nullable: true,
        description: 'Library ID',
        history: new decorators_1.HistoryBuilder().added('v1').deprecated('v1'),
    }),
    __metadata("design:type", Object)
], AssetResponseDto.prototype, "libraryId", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Original file path' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "originalPath", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Original file name' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "originalFileName", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({
        type: 'string',
        format: 'date-time',
        description: 'The actual UTC timestamp when the file was created/captured, preserving timezone information. This is the authoritative timestamp for chronological sorting within timeline groups. Combined with timezone data, this can be used to determine the exact moment the photo was taken.',
        example: '2024-01-15T19:30:00.000Z',
    }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "fileCreatedAt", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({
        type: 'string',
        format: 'date-time',
        description: 'The UTC timestamp when the file was last modified on the filesystem. This reflects the last time the physical file was changed, which may be different from when the photo was originally taken.',
        example: '2024-01-16T10:15:00.000Z',
    }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "fileModifiedAt", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({
        type: 'string',
        format: 'date-time',
        description: 'The UTC timestamp when the asset record was last updated in the database. This is automatically maintained by the database and reflects when any field in the asset was last modified.',
        example: '2024-01-16T12:45:30.000Z',
    }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "updatedAt", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Is favorite' }),
    __metadata("design:type", Boolean)
], AssetResponseDto.prototype, "isFavorite", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Is archived' }),
    __metadata("design:type", Boolean)
], AssetResponseDto.prototype, "isArchived", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Is trashed' }),
    __metadata("design:type", Boolean)
], AssetResponseDto.prototype, "isTrashed", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Is offline' }),
    __metadata("design:type", Boolean)
], AssetResponseDto.prototype, "isOffline", void 0);
__decorate([
    (0, validation_1.ValidateEnum)({ enum: enum_1.AssetVisibility, name: 'AssetVisibility', description: 'Asset visibility' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "visibility", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: undefined }),
    __metadata("design:type", exif_dto_1.ExifResponseDto)
], AssetResponseDto.prototype, "exifInfo", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: undefined }),
    __metadata("design:type", Array)
], AssetResponseDto.prototype, "tags", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: undefined }),
    __metadata("design:type", Array)
], AssetResponseDto.prototype, "people", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: undefined }),
    __metadata("design:type", Array)
], AssetResponseDto.prototype, "unassignedFaces", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Base64 encoded SHA1 hash' }),
    __metadata("design:type", String)
], AssetResponseDto.prototype, "checksum", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: undefined }),
    __metadata("design:type", Object)
], AssetResponseDto.prototype, "stack", void 0);
__decorate([
    (0, swagger_1.ApiPropertyOptional)({ description: 'Duplicate group ID' }),
    __metadata("design:type", Object)
], AssetResponseDto.prototype, "duplicateId", void 0);
__decorate([
    (0, decorators_1.Property)({ description: 'Is resized', history: new decorators_1.HistoryBuilder().added('v1').deprecated('v1.113.0') }),
    __metadata("design:type", Boolean)
], AssetResponseDto.prototype, "resized", void 0);
__decorate([
    (0, decorators_1.Property)({ description: 'Is edited', history: new decorators_1.HistoryBuilder().added('v2.5.0').beta('v2.5.0') }),
    __metadata("design:type", Boolean)
], AssetResponseDto.prototype, "isEdited", void 0);
class AssetStackResponseDto {
    id;
    primaryAssetId;
    assetCount;
    static _OPENAPI_METADATA_FACTORY() {
        return { id: { required: true, type: () => String }, primaryAssetId: { required: true, type: () => String }, assetCount: { required: true, type: () => Number } };
    }
}
exports.AssetStackResponseDto = AssetStackResponseDto;
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Stack ID' }),
    __metadata("design:type", String)
], AssetStackResponseDto.prototype, "id", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ description: 'Primary asset ID' }),
    __metadata("design:type", String)
], AssetStackResponseDto.prototype, "primaryAssetId", void 0);
__decorate([
    (0, swagger_1.ApiProperty)({ type: 'integer', description: 'Number of assets in stack' }),
    __metadata("design:type", Number)
], AssetStackResponseDto.prototype, "assetCount", void 0);
const peopleWithFaces = (faces, edits, assetDimensions) => {
    if (!faces) {
        return [];
    }
    const peopleFaces = new Map();
    for (const face of faces) {
        if (!face.person) {
            continue;
        }
        if (!peopleFaces.has(face.person.id)) {
            peopleFaces.set(face.person.id, {
                ...(0, person_dto_1.mapPerson)(face.person),
                faces: [],
            });
        }
        const mappedFace = (0, person_dto_1.mapFacesWithoutPerson)(face, edits, assetDimensions);
        peopleFaces.get(face.person.id).faces.push(mappedFace);
    }
    return [...peopleFaces.values()];
};
const mapStack = (entity) => {
    if (!entity.stack) {
        return null;
    }
    return {
        id: entity.stack.id,
        primaryAssetId: entity.stack.primaryAssetId,
        assetCount: entity.stack.assetCount ?? entity.stack.assets.length + 1,
    };
};
function mapAsset(entity, options = {}) {
    const { stripMetadata = false, withStack = false } = options;
    if (stripMetadata) {
        const sanitizedAssetResponse = {
            id: entity.id,
            type: entity.type,
            originalMimeType: mime_types_1.mimeTypes.lookup(entity.originalFileName),
            thumbhash: entity.thumbhash ? (0, bytes_1.hexOrBufferToBase64)(entity.thumbhash) : null,
            localDateTime: (0, date_1.asDateString)(entity.localDateTime),
            duration: entity.duration ?? '0:00:00.00000',
            livePhotoVideoId: entity.livePhotoVideoId,
            hasMetadata: false,
            width: entity.width,
            height: entity.height,
        };
        return sanitizedAssetResponse;
    }
    const assetDimensions = entity.exifInfo ? (0, asset_util_1.getDimensions)(entity.exifInfo) : undefined;
    return {
        id: entity.id,
        createdAt: (0, date_1.asDateString)(entity.createdAt),
        deviceAssetId: entity.deviceAssetId,
        ownerId: entity.ownerId,
        owner: entity.owner ? (0, user_dto_1.mapUser)(entity.owner) : undefined,
        deviceId: entity.deviceId,
        libraryId: entity.libraryId,
        type: entity.type,
        originalPath: entity.originalPath,
        originalFileName: entity.originalFileName,
        originalMimeType: mime_types_1.mimeTypes.lookup(entity.originalFileName),
        thumbhash: entity.thumbhash ? (0, bytes_1.hexOrBufferToBase64)(entity.thumbhash) : null,
        fileCreatedAt: (0, date_1.asDateString)(entity.fileCreatedAt),
        fileModifiedAt: (0, date_1.asDateString)(entity.fileModifiedAt),
        localDateTime: (0, date_1.asDateString)(entity.localDateTime),
        updatedAt: (0, date_1.asDateString)(entity.updatedAt),
        isFavorite: options.auth?.user.id === entity.ownerId && entity.isFavorite,
        isArchived: entity.visibility === enum_1.AssetVisibility.Archive,
        isTrashed: !!entity.deletedAt,
        visibility: entity.visibility,
        duration: entity.duration ?? '0:00:00.00000',
        exifInfo: entity.exifInfo ? (0, exif_dto_1.mapExif)(entity.exifInfo) : undefined,
        livePhotoVideoId: entity.livePhotoVideoId,
        tags: entity.tags?.map((tag) => (0, tag_dto_1.mapTag)(tag)),
        people: peopleWithFaces(entity.faces, entity.edits, assetDimensions),
        unassignedFaces: entity.faces
            ?.filter((face) => !face.person)
            .map((face) => (0, person_dto_1.mapFacesWithoutPerson)(face, entity.edits, assetDimensions)),
        checksum: (0, bytes_1.hexOrBufferToBase64)(entity.checksum),
        stack: withStack ? mapStack(entity) : undefined,
        isOffline: entity.isOffline,
        hasMetadata: true,
        duplicateId: entity.duplicateId,
        resized: true,
        width: entity.width,
        height: entity.height,
        isEdited: entity.isEdited,
    };
}
//# sourceMappingURL=asset-response.dto.js.map