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

#include <vector>

#include "include/utils/SkNoDrawCanvas.h"
#include "modules/svg/src/SkSVGTextPriv.h"
#include "tests/Test.h"

DEF_TEST(Svg_Text_PosProvider, r) {
    const auto L = [](float x) { return SkSVGLength(x); };
    const float N = SkSVGTextContext::PosAttrs()[SkSVGTextContext::PosAttrs::kX];

    static const struct PosTestDesc {
        size_t                   offseta;
        std::vector<SkSVGLength> xa, ya;

        size_t                   offsetb;
        std::vector<SkSVGLength> xb, yb;

        std::vector<SkPoint>     expected;
    } gTests[] = {
        {
            0, {}, {},
            0, {}, {},

            { {N,N} }
        },

        {
            0, { L(1) }, {},
            0, {      }, {},

            { {1,N}, {N,N} }
        },
        {
            0, {       }, {},
            0, { L(10) }, {},

            { {10,N}, {N,N} }
        },
        {
            0, { L( 1) }, {},
            0, { L(10) }, {},

            { {10,N}, {N,N} }
        },
        {
            0, { L( 1), L(2) }, {},
            0, { L(10)       }, {},

            { {10,N}, {2,N}, {N,N} }
        },
        {
            0, { L(1), L( 2) }, {},
            1, {       L(20) }, {},

            { {1,N}, {20,N}, {N,N} }
        },
        {
            0, { L(1), L( 2), L(3) }, {},
            1, {       L(20)       }, {},

            { {1,N}, {20,N}, {3,N}, {N,N} }
        },
        {
            0, { L(1), L(2), L( 3) }, {},
            2, {             L(30) }, {},

            { {1,N}, {2,N}, {30,N}, {N,N} }
        },
        {
            0, { L(1)              }, {},
            2, {             L(30) }, {},

            { {1,N}, {N,N}, {30,N}, {N,N} }
        },


        {
            0, {}, { L(4) },
            0, {}, {      },

            { {N,4}, {N,N} }
        },
        {
            0, {}, {       },
            0, {}, { L(40) },

            { {N,40}, {N,N} }
        },
        {
            0, {}, { L( 4) },
            0, {}, { L(40) },

            { {N,40}, {N,N} }
        },
        {
            0, {}, { L( 4), L(5) },
            0, {}, { L(40)       },

            { {N,40}, {N,5}, {N,N} }
        },
        {
            0, {}, { L(4), L( 5) },
            1, {}, {       L(50) },

            { {N,4}, {N,50}, {N,N} }
        },
        {
            0, {}, { L(4), L( 5), L(6) },
            1, {}, {       L(50)       },

            { {N,4}, {N,50}, {N,6}, {N,N} }
        },
        {
            0, {}, { L(4), L(5), L( 6) },
            2, {}, {             L(60) },

            { {N,4}, {N,5}, {N,60}, {N,N} }
        },
        {
            0, {}, { L(4)              },
            2, {}, {             L(60) },

            { {N,4}, {N,N}, {N,60}, {N,N} }
        },

        {
            0, { L( 1), L(2)}, { L( 4)        },
            0, { L(10)      }, { L(40), L(50) },

            { {10,40}, {2,50}, {N,N} }
        },
        {
            0, { L(1), L( 2), L(3) }, { L(4), L( 5)        },
            1, {       L(20)       }, {       L(50), L(60) },

            { {1,4}, {20,50}, {3,60}, {N,N} }
        },
    };

    const SkSVGTextContext::ShapedTextCallback mock_cb =
        [](const SkSVGRenderContext&, const sk_sp<SkTextBlob>&, const SkPaint*, const SkPaint*) {};

    auto test = [&](const PosTestDesc& tst) {
        auto a = SkSVGText::Make();
        auto b = SkSVGTSpan::Make();
        a->appendChild(b);

        a->setX(tst.xa);
        a->setY(tst.ya);
        b->setX(tst.xb);
        b->setY(tst.yb);

        const SkSVGIDMapper mapper;
        const SkSVGLengthContext lctx({0,0});
        const SkSVGPresentationContext pctx;
        SkNoDrawCanvas canvas(0, 0);
        sk_sp<SkFontMgr> fmgr;
        sk_sp<skresources::ResourceProvider> rp;
        const SkSVGRenderContext ctx(&canvas, fmgr, rp, mapper, lctx, pctx, {nullptr, nullptr});

        SkSVGTextContext tctx(ctx, mock_cb);
        SkSVGTextContext::ScopedPosResolver pa(*a, lctx, &tctx, tst.offseta);
        SkSVGTextContext::ScopedPosResolver pb(*b, lctx, &tctx, tst.offsetb);

        for (size_t i = 0; i < tst.expected.size(); ++i) {
            const auto& exp = tst.expected[i];
            auto pos = i >= tst.offsetb ? pb.resolve(i) : pa.resolve(i);

            REPORTER_ASSERT(r, pos[SkSVGTextContext::PosAttrs::kX] == exp.fX);
            REPORTER_ASSERT(r, pos[SkSVGTextContext::PosAttrs::kY] == exp.fY);
        }
    };

    for (const auto& tst : gTests) {
        test(tst);
    }
}
