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

#include "experimental/svg/model/SkSVGPattern.h"

#include "experimental/svg/model/SkSVGRenderContext.h"
#include "experimental/svg/model/SkSVGValue.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkShader.h"

SkSVGPattern::SkSVGPattern() : INHERITED(SkSVGTag::kPattern) {}

void SkSVGPattern::setX(const SkSVGLength& x) {
    fAttributes.fX.set(x);
}

void SkSVGPattern::setY(const SkSVGLength& y) {
    fAttributes.fY.set(y);
}

void SkSVGPattern::setWidth(const SkSVGLength& w) {
    fAttributes.fWidth.set(w);
}

void SkSVGPattern::setHeight(const SkSVGLength& h) {
    fAttributes.fHeight.set(h);
}

void SkSVGPattern::setHref(const SkSVGStringType& href) {
    fHref = std::move(href);
}

void SkSVGPattern::setPatternTransform(const SkSVGTransformType& patternTransform) {
    fAttributes.fPatternTransform.set(patternTransform);
}

void SkSVGPattern::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
    switch (attr) {
    case SkSVGAttribute::kX:
        if (const auto* x = v.as<SkSVGLengthValue>()) {
            this->setX(*x);
        }
        break;
    case SkSVGAttribute::kY:
        if (const auto* y = v.as<SkSVGLengthValue>()) {
            this->setY(*y);
        }
        break;
    case SkSVGAttribute::kWidth:
        if (const auto* w = v.as<SkSVGLengthValue>()) {
            this->setWidth(*w);
        }
        break;
    case SkSVGAttribute::kHeight:
        if (const auto* h = v.as<SkSVGLengthValue>()) {
            this->setHeight(*h);
        }
        break;
    case SkSVGAttribute::kHref:
        if (const auto* href = v.as<SkSVGStringValue>()) {
            this->setHref(*href);
        }
        break;
    case SkSVGAttribute::kPatternTransform:
        if (const auto* t = v.as<SkSVGTransformValue>()) {
            this->setPatternTransform(*t);
        }
        break;
    default:
        this->INHERITED::onSetAttribute(attr, v);
    }
}

const SkSVGPattern* SkSVGPattern::hrefTarget(const SkSVGRenderContext& ctx) const {
    if (fHref.isEmpty()) {
        return nullptr;
    }

    const auto href = ctx.findNodeById(fHref);
    if (!href || href->tag() != SkSVGTag::kPattern) {
        return nullptr;
    }

    return static_cast<const SkSVGPattern*>(href.get());
}

template <typename T>
bool inherit_if_needed(const SkTLazy<T>& src, SkTLazy<T>& dst) {
    if (!dst.isValid()) {
        dst = src;
        return true;
    }

    return false;
}

/* https://www.w3.org/TR/SVG11/pservers.html#PatternElementHrefAttribute
 *
 * Any attributes which are defined on the referenced element which are not defined on this element
 * are inherited by this element. If this element has no children, and the referenced element does
 * (possibly due to its own ‘xlink:href’ attribute), then this element inherits the children from
 * the referenced element. Inheritance can be indirect to an arbitrary level; thus, if the
 * referenced element inherits attributes or children due to its own ‘xlink:href’ attribute, then
 * the current element can inherit those attributes or children.
 */
const SkSVGPattern* SkSVGPattern::resolveHref(const SkSVGRenderContext& ctx,
                                              PatternAttributes* attrs) const {
    const SkSVGPattern *currentNode = this,
                       *contentNode = this;
    do {
        // Bitwise OR to avoid short-circuiting.
        const bool didInherit =
            inherit_if_needed(currentNode->fAttributes.fX               , attrs->fX)      |
            inherit_if_needed(currentNode->fAttributes.fY               , attrs->fY)      |
            inherit_if_needed(currentNode->fAttributes.fWidth           , attrs->fWidth)  |
            inherit_if_needed(currentNode->fAttributes.fHeight          , attrs->fHeight) |
            inherit_if_needed(currentNode->fAttributes.fPatternTransform, attrs->fPatternTransform);

        if (!contentNode->hasChildren()) {
            contentNode = currentNode;
        }

        if (contentNode->hasChildren() && !didInherit) {
            // All attributes have been resolved, and a valid content node has been found.
            // We can terminate the href chain early.
            break;
        }

        // TODO: reference loop mitigation.
        currentNode = currentNode->hrefTarget(ctx);
    } while (currentNode);

    return contentNode;
}

bool SkSVGPattern::onAsPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
    PatternAttributes attrs;
    const auto* contentNode = this->resolveHref(ctx, &attrs);

    const auto tile = ctx.lengthContext().resolveRect(
            attrs.fX.isValid()      ? *attrs.fX.get()      : SkSVGLength(0),
            attrs.fY.isValid()      ? *attrs.fY.get()      : SkSVGLength(0),
            attrs.fWidth.isValid()  ? *attrs.fWidth.get()  : SkSVGLength(0),
            attrs.fHeight.isValid() ? *attrs.fHeight.get() : SkSVGLength(0));

    if (tile.isEmpty()) {
        return false;
    }

    const SkMatrix* patternTransform = attrs.fPatternTransform.isValid()
            ? attrs.fPatternTransform.get()
            : nullptr;

    SkPictureRecorder recorder;
    SkSVGRenderContext recordingContext(ctx, recorder.beginRecording(tile));

    // Cannot call into INHERITED:: because SkSVGHiddenContainer skips rendering.
    contentNode->SkSVGContainer::onRender(recordingContext);

    paint->setShader(recorder.finishRecordingAsPicture()->makeShader(
                                                 SkTileMode::kRepeat,
                                                 SkTileMode::kRepeat,
                                                 patternTransform,
                                                 &tile));
    return true;
}
