void ShapeAnnotationImpl::updateStyle(Style& style) {
    if (style.getLayer(layerID))
        return;

    if (shape.properties.is<LineAnnotationProperties>()) {
        type = ProjectedFeatureType::LineString;

        std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>();
        layer->type = StyleLayerType::Line;
        layer->layout.join = JoinType::Round;

        const LineAnnotationProperties& properties = shape.properties.get<LineAnnotationProperties>();
        layer->paint.opacity = properties.opacity;
        layer->paint.width = properties.width;
        layer->paint.color = properties.color;

        layer->id = layerID;
        layer->source = AnnotationManager::SourceID;
        layer->sourceLayer = layer->id;

        style.addLayer(std::move(layer), AnnotationManager::PointLayerID);

    } else if (shape.properties.is<FillAnnotationProperties>()) {
        type = ProjectedFeatureType::Polygon;

        std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
        layer->type = StyleLayerType::Fill;

        const FillAnnotationProperties& properties = shape.properties.get<FillAnnotationProperties>();
        layer->paint.opacity = properties.opacity;
        layer->paint.color = properties.color;
        layer->paint.outlineColor = properties.outlineColor;

        layer->id = layerID;
        layer->source = AnnotationManager::SourceID;
        layer->sourceLayer = layer->id;

        style.addLayer(std::move(layer), AnnotationManager::PointLayerID);

    } else {
        const StyleLayer* sourceLayer = style.getLayer(shape.properties.get<std::string>());
        if (!sourceLayer) return;

        std::unique_ptr<StyleLayer> layer = sourceLayer->clone();

        type = layer->type == StyleLayerType::Line
            ? ProjectedFeatureType::LineString
            : ProjectedFeatureType::Polygon;

        layer->id = layerID;
        layer->ref = "";
        layer->source = AnnotationManager::SourceID;
        layer->sourceLayer = layer->id;
        layer->visibility = VisibilityType::Visible;

        style.addLayer(std::move(layer), sourceLayer->id);
    }
}
void AnnotationManager::updateStyle(Style& style) {
    // Create annotation source, point layer, and point bucket
    if (!style.getSource(SourceID)) {
        std::unique_ptr<Source> source = std::make_unique<Source>(SourceType::Annotations, SourceID, "", util::tileSize, std::make_unique<SourceInfo>(), nullptr);
        source->enabled = true;
        style.addSource(std::move(source));

        std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>();
        layer->id = PointLayerID;
        layer->source = SourceID;
        layer->sourceLayer = PointLayerID;
        layer->layout.icon.image = std::string("{sprite}");
        layer->layout.icon.allowOverlap = true;
        layer->spriteAtlas = &spriteAtlas;

        style.addLayer(std::move(layer));
    }

    for (const auto& shape : shapeAnnotations) {
        shape.second->updateStyle(style);
    }

    for (const auto& layer : obsoleteShapeAnnotationLayers) {
        if (style.getLayer(layer)) {
            style.removeLayer(layer);
        }
    }

    obsoleteShapeAnnotationLayers.clear();

    for (auto& monitor : monitors) {
        monitor->update(getTile(monitor->tileID));
    }
}
void AnnotationManager::updateStyle(Style& style) {
    // Create annotation source, point layer, and point bucket
    if (!style.getSource(SourceID)) {
        std::unique_ptr<Source> source = std::make_unique<AnnotationSource>();
        source->baseImpl->enabled = true;
        style.addSource(std::move(source));

        std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID, SourceID);

        layer->setSourceLayer(PointLayerID);
        layer->setIconImage({"{sprite}"});
        layer->setIconAllowOverlap(true);

        layer->impl->spriteAtlas = &spriteAtlas;

        style.addLayer(std::move(layer));
    }

    for (const auto& shape : shapeAnnotations) {
        shape.second->updateStyle(style);
    }

    for (const auto& layer : obsoleteShapeAnnotationLayers) {
        if (style.getLayer(layer)) {
            style.removeLayer(layer);
        }
    }

    obsoleteShapeAnnotationLayers.clear();
}
void AnnotationManager::updateStyle(Style& style) {
    // Create annotation source, point layer, and point bucket
    if (!style.getSource(SourceID)) {
        std::unique_ptr<Source> source = std::make_unique<Source>();
        source->info.type = SourceType::Annotations;
        source->info.source_id = SourceID;
        source->enabled = true;
        style.addSource(std::move(source));

        std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>();
        layer->id = PointLayerID;
        layer->type = StyleLayerType::Symbol;
        layer->styles.emplace(ClassID::Default, ClassProperties());

        layer->bucket = std::make_shared<StyleBucket>(layer->type);
        layer->bucket->name = layer->id;
        layer->bucket->source = SourceID;
        layer->bucket->source_layer = PointLayerID;
        layer->bucket->layout.set(PropertyKey::IconImage, ConstantFunction<std::string>("{sprite}"));
        layer->bucket->layout.set(PropertyKey::IconAllowOverlap, ConstantFunction<bool>(true));

        style.addLayer(std::move(layer));
    }

    for (const auto& shape : shapeAnnotations) {
        shape.second->updateStyle(style);
    }

    for (const auto& layer : obsoleteShapeAnnotationLayers) {
        style.removeLayer(layer);
    }

    obsoleteShapeAnnotationLayers.clear();
    style.getSource(SourceID)->invalidateTiles();
}
void LineAnnotationImpl::updateStyle(Style& style) const {
    if (style.getLayer(layerID))
        return;

    std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>(layerID, AnnotationManager::SourceID);
    layer->setSourceLayer(layerID);
    layer->setLineJoin(LineJoinType::Round);
    layer->setLineOpacity(annotation.opacity);
    layer->setLineWidth(annotation.width);
    layer->setLineColor(annotation.color);

    style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
}
void FillAnnotationImpl::updateStyle(Style& style) const {
    Layer* layer = style.getLayer(layerID);

    if (!layer) {
        auto newLayer = std::make_unique<FillLayer>(layerID, AnnotationManager::SourceID);
        newLayer->setSourceLayer(layerID);
        layer = style.addLayer(std::move(newLayer), AnnotationManager::PointLayerID);
    }

    FillLayer* fillLayer = layer->as<FillLayer>();
    fillLayer->setFillOpacity(annotation.opacity);
    fillLayer->setFillColor(annotation.color);
    fillLayer->setFillOutlineColor(annotation.outlineColor);
}
void LineAnnotationImpl::updateStyle(Style& style) const {
    Layer* layer = style.getLayer(layerID);

    if (!layer) {
        auto newLayer = std::make_unique<LineLayer>(layerID, AnnotationManager::SourceID);
        newLayer->setSourceLayer(layerID);
        newLayer->setLineJoin(LineJoinType::Round);
        layer = style.addLayer(std::move(newLayer), AnnotationManager::PointLayerID);
    }

    LineLayer* lineLayer = layer->as<LineLayer>();
    lineLayer->setLineOpacity(annotation.opacity);
    lineLayer->setLineWidth(annotation.width);
    lineLayer->setLineColor(annotation.color);
}