#include "overlay_image_info.h"
#include "storage.h"

#include <maps/libs/geolib/include/point.h>
#include <maps/libs/geolib/include/vector.h>

using namespace maps::geolib3;

namespace maps::wiki::renderer_overlay {
OverlayImageInfo
OverlayImageInfo::fromJson(json::Value value)
{
    OverlayImageInfo info {
        value["uuid"].toString(),
        boost::lexical_cast<OverlayMethod>(value["method"].toString()),
        value["zOrder"].as<size_t>(),
        {},
        {},
        {}
    };
    info.mapping.reserve(value["methodParameters"].size());
    for (size_t i = 0; i < value["methodParameters"].size(); ++i) {
        auto pairValue = value["methodParameters"][i];
        info.mapping.emplace_back(
            PixelMapping {
                Point2 {pairValue[0][0].as<double>(), pairValue[0][1].as<double>()},
                Point2 {pairValue[1][0].as<double>(), pairValue[1][1].as<double>()},
            }
        );
    }
    if (value.hasField("origin")) {
        const auto& origin = value["origin"];
        const Vector2 originVector(origin[0].as<double>(), origin[1].as<double>());
        for (auto& pixelMapping : info.mapping) {
            pixelMapping.mapCoord += originVector;
        }
    }
    return info;
}

OverlayImageInfoByZOrder readFromImagesArgByZOrder(
    const std::string& images,
    size_t zoom)
{
    const auto imagesJson = json::Value::fromString(images);
    ASSERT(imagesJson.isArray());
    OverlayImageInfoByZOrder overlayImageInfoByZOrder;
    for (size_t i = 0; i < imagesJson.size(); ++i) {
        overlayImageInfoByZOrder.emplace(
            imagesJson[i]["zOrder"].as<size_t>(),
            OverlayImageInfo::fromJson(imagesJson[i]));
    }
    //TODO check images/tile geometry intersection and skip infos/entire tile
    for (auto& [_, overlayImageInfo] : overlayImageInfoByZOrder) {
        overlayImageInfo.image = storage()->read(overlayImageInfo.imageUuid);
        overlayImageInfo.transformation =
            createTransformation(
                zoom,
                overlayImageInfo.method,
                overlayImageInfo.mapping);
    }
    return overlayImageInfoByZOrder;
}
} // namespace maps::wiki::renderer_overlay
