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

#include "experimental/sorttoy/Cmds.h"
#include "experimental/sorttoy/Fake.h"
#include "experimental/sorttoy/SortKey.h"

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRRect.h"
#include "include/effects/SkGradientShader.h"

//------------------------------------------------------------------------------------------------
SortKey SaveCmd::getKey() {
    SkASSERT(0);
    return {};
}

void SaveCmd::execute(FakeCanvas* f) const {
    f->save();
}

void SaveCmd::execute(SkCanvas* c) const {
    c->save();
}

//------------------------------------------------------------------------------------------------
SortKey RestoreCmd::getKey() {
    SkASSERT(0);
    return {};
}

void RestoreCmd::execute(FakeCanvas* f) const {
    f->restore();
}

void RestoreCmd::execute(SkCanvas* c) const {
    c->restore();
}

//------------------------------------------------------------------------------------------------
DrawCmd::DrawCmd(ID id,
                 Shape shape,
                 SkIRect r,
                 const FakePaint& p)
    : Cmd(id)
    , fShape(shape)
    , fRect(r)
    , fPaint(p) {
}

DrawCmd::DrawCmd(ID id,
                 PaintersOrder paintersOrder,
                 Shape shape,
                 SkIRect r,
                 const FakePaint& p,
                 sk_sp<FakeMCBlob> state)
    : Cmd(id)
    , fPaintersOrder(paintersOrder)
    , fShape(shape)
    , fRect(r)
    , fPaint(p)
    , fMCState(std::move(state)) {
}

static bool shared_contains(int x, int y, Shape s, SkIRect r) {
    if (s == Shape::kRect) {
        return r.contains(x, y);
    } else {
        float a = r.width() / 2.0f;   // horizontal radius
        float b = r.height() / 2.0f;  // vertical radius
        float h = 0.5f * (r.fLeft + r.fRight); // center X
        float k = 0.5f * (r.fTop + r.fBottom); // center Y

        float xTerm = x + 0.5f - h;
        float yTerm = y + 0.5f - k;

        return (xTerm * xTerm) / (a * a) + (yTerm * yTerm) / (b * b) < 1.0f;
    }
}

bool DrawCmd::contains(int x, int y) const {
    return shared_contains(x, y, fShape, fRect);
}

uint32_t DrawCmd::getSortZ() const {
    return fPaintersOrder.toUInt();
}

// Opaque and transparent draws both write their painter's index to the depth buffer
uint32_t DrawCmd::getDrawZ() const {
    return fPaintersOrder.toUInt();
}

SortKey DrawCmd::getKey() {
    return SortKey(fPaint.isTransparent(), this->getSortZ(), fPaint.toID());
}

void DrawCmd::execute(FakeCanvas* c) const {
    c->drawShape(fID, fShape, fRect, fPaint);
}

void DrawCmd::execute(SkCanvas* c) const {

    SkColor4f colors[2] = {
        SkColor4f::FromColor(fPaint.c0()),
        SkColor4f::FromColor(fPaint.c1())
    };

    SkPaint p;
    if (fPaint.toID() == kSolidMat) {
        p.setColor(fPaint.c0());
    } else if (fPaint.toID() == kLinearMat) {
        SkPoint pts[] = { { 0.0f, 0.0f, }, { 256.0f, 256.0f } };
        p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, nullptr, 2,
                                                 SkTileMode::kClamp));
    } else {
        SkASSERT(fPaint.toID() == kRadialMat);

        auto shader = SkGradientShader::MakeRadial(SkPoint::Make(128.0f, 128.0f),
                                                   128.0f,
                                                   colors,
                                                   nullptr,
                                                   nullptr,
                                                   2,
                                                   SkTileMode::kRepeat);
        p.setShader(std::move(shader));
    }

    if (fShape == Shape::kRect) {
        c->drawRect(SkRect::Make(fRect), p);
    } else {
        c->drawOval(SkRect::Make(fRect), p);
    }
}

static bool is_opaque(SkColor c) {
    return 0xFF == SkColorGetA(c);
}

void DrawCmd::rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM) const {

    uint32_t z = this->getDrawZ();
    SkIRect scissor = fMCState->scissor();

    for (int y = fRect.fTop; y < fRect.fBottom; ++y) {
        for (int x = fRect.fLeft; x < fRect.fRight; ++x) {
            if (!scissor.contains(x, y)) {
                continue;
            }

            if (!this->contains(x, y)) {
                continue;
            }

            if (z > zBuffer[x][y]) {
                zBuffer[x][y] = z;

                SkColor c = fPaint.evalColor(x, y);

                if (is_opaque(c)) {
                    *dstBM->getAddr32(x, y) = c;
                } else {
                    SkColor4f bot = SkColor4f::FromColor(*dstBM->getAddr32(x, y));
                    SkColor4f top = SkColor4f::FromColor(c);
                    SkColor4f result = {
                        top.fA * top.fR + (1.0f - top.fA) * bot.fR,
                        top.fA * top.fG + (1.0f - top.fA) * bot.fG,
                        top.fA * top.fB + (1.0f - top.fA) * bot.fB,
                                 top.fA + (1.0f - top.fA) * bot.fA
                    };
                    *dstBM->getAddr32(x, y) = result.toSkColor();
                }
            }
        }
    }
}

//------------------------------------------------------------------------------------------------
ClipCmd::ClipCmd(ID id, Shape shape, SkIRect r)
        : Cmd(id)
        , fShape(shape)
        , fRect(r) {
}

ClipCmd::ClipCmd(ID id, PaintersOrder paintersOrderWhenAdded, Shape shape, SkIRect r)
        : Cmd(id)
        , fShape(shape)
        , fRect(r)
        , fPaintersOrderWhenAdded(paintersOrderWhenAdded) {
}

ClipCmd::~ClipCmd() {}

bool ClipCmd::contains(int x, int y) const {
    return shared_contains(x, y, fShape, fRect);
}

uint32_t ClipCmd::getSortZ() const {
    SkASSERT(fPaintersOrderWhenAdded.isValid());

    return fPaintersOrderWhenAdded.toUInt();
}

// A clip writes the painter's index corresponding to when it's "popped" off the clip stack
uint32_t ClipCmd::getDrawZ() const {
    SkASSERT(fPaintersOrderWhenPopped.isValid());

    return fPaintersOrderWhenPopped.toUInt();
}

SortKey ClipCmd::getKey() {
    return SortKey(false, this->getSortZ(), kInvalidMat);
}

void ClipCmd::onAboutToBePopped(PaintersOrder paintersOrderWhenPopped) {
    SkASSERT(!fPaintersOrderWhenPopped.isValid() && paintersOrderWhenPopped.isValid());
    fPaintersOrderWhenPopped = paintersOrderWhenPopped;
}

void ClipCmd::execute(FakeCanvas* c) const {
    // This call is creating the 'real' ClipCmd for the "actual" case
    SkASSERT(!fPaintersOrderWhenAdded.isValid() && !fPaintersOrderWhenPopped.isValid());

    c->clipShape(fID, fShape, fRect);
}

void ClipCmd::execute(SkCanvas* c) const {
    if (fShape == Shape::kRect) {
        c->clipRect(SkRect::Make(fRect));
    } else {
        c->clipRRect(SkRRect::MakeOval(SkRect::Make(fRect)));
    }
}

void ClipCmd::rasterize(uint32_t zBuffer[256][256], SkBitmap* /* dstBM */) const {
    uint32_t drawZ = this->getDrawZ();

    // TODO: limit this via the scissor!
    for (int y = 0; y < 256; ++y) {
        for (int x = 0; x < 256; ++x) {
            if (!this->contains(x, y) && drawZ > zBuffer[x][y]) {
                zBuffer[x][y] = drawZ;
            }
        }
    }
}

//------------------------------------------------------------------------------------------------
