/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "modules/svg/include/SkSVGAttributeParser.h"
#include "modules/svg/include/SkSVGImage.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/include/SkSVGValue.h"
#include "src/utils/SkOSPath.h"

bool SkSVGImage::parseAndSetAttribute(const char* n, const char* v) {
    return INHERITED::parseAndSetAttribute(n, v) ||
           this->setX(SkSVGAttributeParser::parse<SkSVGLength>("x", n, v)) ||
           this->setY(SkSVGAttributeParser::parse<SkSVGLength>("y", n, v)) ||
           this->setWidth(SkSVGAttributeParser::parse<SkSVGLength>("width", n, v)) ||
           this->setHeight(SkSVGAttributeParser::parse<SkSVGLength>("height", n, v)) ||
           this->setHref(SkSVGAttributeParser::parse<SkSVGIRI>("xlink:href", n, v)) ||
           this->setPreserveAspectRatio(SkSVGAttributeParser::parse<SkSVGPreserveAspectRatio>(
                   "preserveAspectRatio", n, v));
}

bool SkSVGImage::onPrepareToRender(SkSVGRenderContext* ctx) const {
    // Width or height of 0 disables rendering per spec:
    // https://www.w3.org/TR/SVG11/struct.html#ImageElement
    return !fHref.iri().isEmpty() && fWidth.value() > 0 && fHeight.value() > 0 &&
           INHERITED::onPrepareToRender(ctx);
}

static sk_sp<SkImage> LoadImage(const sk_sp<skresources::ResourceProvider>& rp,
                                const SkSVGIRI& href) {
    // TODO: It may be better to use the SVG 'id' attribute as the asset id, to allow
    // clients to perform asset substitution based on element id.
    sk_sp<skresources::ImageAsset> imageAsset;
    switch (href.type()) {
        case SkSVGIRI::Type::kDataURI:
            imageAsset = rp->loadImageAsset("", href.iri().c_str(), "");
            break;
        case SkSVGIRI::Type::kNonlocal: {
            const auto path = SkOSPath::Dirname(href.iri().c_str());
            const auto name = SkOSPath::Basename(href.iri().c_str());
            imageAsset = rp->loadImageAsset(path.c_str(), name.c_str(), /* id */ name.c_str());
            break;
        }
        default:
            SkDebugf("error loading image: unhandled iri type %d\n", href.type());
            return nullptr;
    }

    return imageAsset ? imageAsset->getFrameData(0).image : nullptr;
}

SkSVGImage::ImageInfo SkSVGImage::LoadImage(const sk_sp<skresources::ResourceProvider>& rp,
                                            const SkSVGIRI& iri,
                                            const SkRect& viewPort,
                                            SkSVGPreserveAspectRatio par) {
    SkASSERT(rp);

    // TODO: svg sources
    sk_sp<SkImage> image = ::LoadImage(rp, iri);
    if (!image) {
        return {};
    }

    // Per spec: raster content has implicit viewbox of '0 0 width height'.
    const SkRect viewBox = SkRect::Make(image->bounds());

    // Map and place at x, y specified by viewport
    const SkMatrix m = ComputeViewboxMatrix(viewBox, viewPort, par);
    const SkRect dst = m.mapRect(viewBox).makeOffset(viewPort.fLeft, viewPort.fTop);

    return {std::move(image), dst};
}

void SkSVGImage::onRender(const SkSVGRenderContext& ctx) const {
    // Per spec: x, w, width, height attributes establish the new viewport.
    const SkSVGLengthContext& lctx = ctx.lengthContext();
    const SkRect viewPort = lctx.resolveRect(fX, fY, fWidth, fHeight);

    const auto imgInfo = LoadImage(ctx.resourceProvider(), fHref, viewPort, fPreserveAspectRatio);
    if (!imgInfo.fImage) {
        SkDebugf("can't render image: load image failed\n");
        return;
    }

    // TODO: image-rendering property
    ctx.canvas()->drawImageRect(
            imgInfo.fImage, imgInfo.fDst, SkSamplingOptions(SkFilterMode::kLinear));
}

SkPath SkSVGImage::onAsPath(const SkSVGRenderContext&) const { return {}; }

SkRect SkSVGImage::onObjectBoundingBox(const SkSVGRenderContext& ctx) const {
    const SkSVGLengthContext& lctx = ctx.lengthContext();
    return lctx.resolveRect(fX, fY, fWidth, fHeight);
}
