#include "skia_renderer.hpp"
#include "SkGradientShader.h"
#include "SkPath.h"
#include "rive/math/vec2d.hpp"
#include "rive/shapes/paint/color.hpp"
#include "to_skia.hpp"

using namespace rive;

void SkiaRenderPath::fillRule(FillRule value) {
    switch (value) {
        case FillRule::evenOdd:
            m_Path.setFillType(SkPathFillType::kEvenOdd);
            break;
        case FillRule::nonZero:
            m_Path.setFillType(SkPathFillType::kWinding);
            break;
    }
}

void SkiaRenderPath::reset() { m_Path.reset(); }
void SkiaRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform) {
    m_Path.addPath(reinterpret_cast<SkiaRenderPath*>(path)->m_Path,
                   ToSkia::convert(transform));
}

void SkiaRenderPath::moveTo(float x, float y) { m_Path.moveTo(x, y); }
void SkiaRenderPath::lineTo(float x, float y) { m_Path.lineTo(x, y); }
void SkiaRenderPath::cubicTo(
    float ox, float oy, float ix, float iy, float x, float y) {
    m_Path.cubicTo(ox, oy, ix, iy, x, y);
}
void SkiaRenderPath::close() { m_Path.close(); }

SkiaRenderPaint::SkiaRenderPaint() { m_Paint.setAntiAlias(true); }

void SkiaRenderPaint::style(RenderPaintStyle style) {
    switch (style) {
        case RenderPaintStyle::fill:
            m_Paint.setStyle(SkPaint::Style::kFill_Style);
            break;
        case RenderPaintStyle::stroke:
            m_Paint.setStyle(SkPaint::Style::kStroke_Style);
            break;
    }
}
void SkiaRenderPaint::color(unsigned int value) { m_Paint.setColor(value); }
void SkiaRenderPaint::thickness(float value) { m_Paint.setStrokeWidth(value); }
void SkiaRenderPaint::join(StrokeJoin value) {
    m_Paint.setStrokeJoin(ToSkia::convert(value));
}
void SkiaRenderPaint::cap(StrokeCap value) {
    m_Paint.setStrokeCap(ToSkia::convert(value));
}

void SkiaRenderPaint::linearGradient(float sx, float sy, float ex, float ey) {
    m_GradientBuilder = new SkiaLinearGradientBuilder(sx, sy, ex, ey);
}
void SkiaRenderPaint::radialGradient(float sx, float sy, float ex, float ey) {
    m_GradientBuilder = new SkiaRadialGradientBuilder(sx, sy, ex, ey);
}
void SkiaRenderPaint::addStop(unsigned int color, float stop) {
    m_GradientBuilder->stops.emplace_back(GradientStop(color, stop));
}
void SkiaRenderPaint::completeGradient() {
    m_GradientBuilder->make(m_Paint);
    delete m_GradientBuilder;
}

void SkiaRenderPaint::blendMode(BlendMode value) {
    m_Paint.setBlendMode(ToSkia::convert(value));
}

void SkiaRadialGradientBuilder::make(SkPaint& paint) {
    int numStops = stops.size();

    SkColor colors[numStops];
    SkScalar pos[numStops];

    for (int i = 0; i < numStops; i++) {
        const GradientStop& stop = stops[i];
        colors[i] = SkColor(stop.color);
        pos[i] = stop.stop;
    }

    float radius = Vec2D::distance(Vec2D(sx, sy), Vec2D(ex, ey));
    paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(sx, sy),
                                                 radius,
                                                 colors,
                                                 pos,
                                                 numStops,
                                                 SkTileMode::kClamp,
                                                 0,
                                                 nullptr));
}

void SkiaLinearGradientBuilder::make(SkPaint& paint) {
    int numStops = stops.size();
    SkPoint points[2] = {SkPoint::Make(sx, sy), SkPoint::Make(ex, ey)};
    SkColor colors[numStops];
    SkScalar pos[numStops];

    for (int i = 0; i < numStops; i++) {
        const GradientStop& stop = stops[i];
        colors[i] = SkColor(stop.color);
        pos[i] = stop.stop;
    }
    paint.setShader(SkGradientShader::MakeLinear(
        points, colors, pos, numStops, SkTileMode::kClamp, 0, nullptr));
}

void SkiaRenderer::save() { m_Canvas->save(); }
void SkiaRenderer::restore() { m_Canvas->restore(); }
void SkiaRenderer::transform(const Mat2D& transform) {
    m_Canvas->concat(ToSkia::convert(transform));
}
void SkiaRenderer::drawPath(RenderPath* path, RenderPaint* paint) {
    m_Canvas->drawPath(reinterpret_cast<SkiaRenderPath*>(path)->path(),
                       reinterpret_cast<SkiaRenderPaint*>(paint)->paint());
}

void SkiaRenderer::clipPath(RenderPath* path) {
    m_Canvas->clipPath(reinterpret_cast<SkiaRenderPath*>(path)->path(), true);
}

void SkiaRenderer::drawImage(RenderImage* image,
                             BlendMode blendMode,
                             float opacity) {
    SkPaint paint;
    paint.setAlphaf(opacity);
    paint.setBlendMode(ToSkia::convert(blendMode));
    auto skiaImage = reinterpret_cast<SkiaRenderImage*>(image);
    SkSamplingOptions samplingOptions(SkFilterMode::kLinear,
                                      SkMipmapMode::kNone);
    m_Canvas->drawImage(
        skiaImage->skImage(), 0.0f, 0.0f, samplingOptions, &paint);
}

bool SkiaRenderImage::decode(const uint8_t* bytes, std::size_t size) {

    sk_sp<SkData> data = SkData::MakeWithoutCopy(bytes, size);
    m_SkImage = SkImage::MakeFromEncoded(data);
    m_Width = m_SkImage->width();
    m_Height = m_SkImage->height();
    return true;
}

namespace rive {
    RenderPath* makeRenderPath() { return new SkiaRenderPath(); }
    RenderPaint* makeRenderPaint() { return new SkiaRenderPaint(); }
    RenderImage* makeRenderImage() { return new SkiaRenderImage(); }
} // namespace rive