void HTTPAndroidRequest::onResponse(JNIEnv* env, int code, jstring /* message */, jstring etag, jstring modified, jstring cacheControl, jstring expires, jbyteArray body) {
    response = std::make_unique<Response>();
    using Error = Response::Error;

    if (etag != nullptr) {
        response->etag = mbgl::android::std_string_from_jstring(env, etag);
    }

    if (modified != nullptr) {
        response->modified = util::parseTimePoint(mbgl::android::std_string_from_jstring(env, modified).c_str());
    }

    if (cacheControl != nullptr) {
        response->expires = parseCacheControl(mbgl::android::std_string_from_jstring(env, cacheControl).c_str());
    }

    if (expires != nullptr) {
        response->expires = util::parseTimePoint(mbgl::android::std_string_from_jstring(env, expires).c_str());
    }

    if (code == 200) {
        if (body != nullptr) {
            jbyte* bodyData = env->GetByteArrayElements(body, nullptr);
            response->data = std::make_shared<std::string>(reinterpret_cast<char*>(bodyData), env->GetArrayLength(body));
            env->ReleaseByteArrayElements(body, bodyData, JNI_ABORT);
        } else {
            response->data = std::make_shared<std::string>();
        }
    } else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
        response->noContent = true;
    } else if (code == 304) {
        response->notModified = true;
    } else if (code == 404) {
        response->error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
    } else if (code >= 500 && code < 600) {
        response->error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + std::to_string(code));
    } else {
        response->error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + std::to_string(code));
    }

    async.send();
}
void HTTPAndroidRequest::onFailure(int type, std::string message) {
    response = std::make_unique<Response>();
    using Error = Response::Error;

    switch (type) {
        case connectionError:
            response->error = std::make_unique<Error>(Error::Reason::Connection, message);
            break;
        case temporaryError:
            response->error = std::make_unique<Error>(Error::Reason::Server, message);
            break;
        case canceledError:
            response->error = std::make_unique<Error>(Error::Reason::Canceled, "Request was cancelled");
            break;
        default:
            response->error = std::make_unique<Error>(Error::Reason::Other, message);
    }

    async.send();
}
void HTTPAndroidRequest::onFailure(JNIEnv* env, int type, jstring message) {
    std::string messageStr = mbgl::android::std_string_from_jstring(env, message);

    response = std::make_unique<Response>();
    using Error = Response::Error;

    switch (type) {
        case connectionError:
            response->error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
            break;
        case temporaryError:
            response->error = std::make_unique<Error>(Error::Reason::Server, messageStr);
            break;
        case canceledError:
            response.reset();
            break;
        default:
            response->error = std::make_unique<Error>(Error::Reason::Other, messageStr);
    }

    async.send();
}
void HTTPAndroidRequest::onResponse(int code, std::string message, std::string etag, std::string modified, std::string cacheControl, std::string expires, std::string body) {
    response = std::make_unique<Response>();
    using Error = Response::Error;

    response->modified = Seconds(parse_date(modified.c_str()));
    response->etag = etag;
    response->expires = parseCacheControl(cacheControl.c_str());
    if (!expires.empty()) {
        response->expires = Seconds(parse_date(expires.c_str()));
    }
    response->data = std::make_shared<std::string>(body);

    if (code == 200) {
        // Nothing to do; this is what we want
    } else if (code == 304) {
        if (existingResponse) {
            if (existingResponse->error) {
                response->error = std::make_unique<Error>(*existingResponse->error);
            }
            response->data = existingResponse->data;
            response->modified = existingResponse->modified;
            // We're not updating `expired`, it was probably set during the request.
            response->etag = existingResponse->etag;
        } else {
            // This is an unsolicited 304 response and should only happen on malfunctioning
            // HTTP servers. It likely doesn't include any data, but we don't have much options.
        }
    } else if (code == 404) {
        response->error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
    } else if (code >= 500 && code < 600) {
        response->error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + std::to_string(code));
    } else {
        response->error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + std::to_string(code));
    }

    async.send();
}