module attachment.api;

import handy_http_primitives;
import handy_http_data.json;
import handy_http_handlers.path_handler : PathMapping;
import std.conv;

import profile.data;
import profile.data_impl_sqlite;
import profile.service;
import auth.service;
import auth.model;
import util.data;
import attachment.data;
import attachment.model;

/** 
 * Handles downloading of an attachment. Because the browser is doing the
 * downloading instead of a Javascript client, this means we have to embed the
 * user's auth token in the query parameters and deal with it differently from
 * normal authenticated requests.
 * Params:
 *   request = The HTTP request.
 *   response = The HTTP response.
 */
@PathMapping(HttpMethod.GET, "/api/profiles/:profile/attachments/:attachmentId/download")
void handleDownloadAttachment(ref ServerHttpRequest request, ref ServerHttpResponse response) {
    Optional!AuthContext authCtx = extractAuthContextFromQueryParam(request, response);
    if (authCtx.isNull) return;
    User user = authCtx.value.user;
    string profileName = request.getPathParamOrThrow!string("profile");
    ProfileRepository repo = new FileSystemProfileRepository(user.username);
    ProfileContext profileCtx = repo.findByName(profileName)
        .mapIfPresent!(p => ProfileContext(p, user))
        .orElseThrow(() => new HttpStatusException(HttpStatus.NOT_FOUND));
    ProfileDataSource ds = getProfileDataSource(profileCtx);

    ulong attachmentId = request.getPathParamOrThrow!ulong("attachmentId");
    AttachmentRepository attachmentRepo = ds.getAttachmentRepository();
    Attachment attachment = attachmentRepo.findById(attachmentId)
        .orElseThrow(() => new HttpStatusException(HttpStatus.NOT_FOUND, "Attachment not found."));
    ubyte[] content = attachmentRepo.getContent(attachment.id)
        .orElseThrow(() => new HttpStatusException(
            HttpStatus.INTERNAL_SERVER_ERROR,
            "Couldn't get content for attachment."
        ));
    response.headers.add("Content-Disposition", "attachment; filename=\"" ~ attachment.filename ~ "\"");
    response.writeBodyBytes(content, attachment.contentType);
}