/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "RecordingCanvas.h"

#include "DeferredLayerUpdater.h"
#include "RecordedOp.h"
#include "RenderNode.h"
#include "VectorDrawable.h"

namespace android {
namespace uirenderer {

RecordingCanvas::RecordingCanvas(size_t width, size_t height)
        : mState(*this)
        , mResourceCache(ResourceCache::getInstance()) {
    resetRecording(width, height);
}

RecordingCanvas::~RecordingCanvas() {
    LOG_ALWAYS_FATAL_IF(mDisplayList,
            "Destroyed a RecordingCanvas during a record!");
}

void RecordingCanvas::resetRecording(int width, int height) {
    LOG_ALWAYS_FATAL_IF(mDisplayList,
            "prepareDirty called a second time during a recording!");
    mDisplayList = new DisplayList();

    mState.initializeRecordingSaveStack(width, height);

    mDeferredBarrierType = DeferredBarrierType::InOrder;
    mState.setDirtyClip(false);
}

DisplayList* RecordingCanvas::finishRecording() {
    restoreToCount(1);
    mPaintMap.clear();
    mRegionMap.clear();
    mPathMap.clear();
    DisplayList* displayList = mDisplayList;
    mDisplayList = nullptr;
    mSkiaCanvasProxy.reset(nullptr);
    return displayList;
}

SkCanvas* RecordingCanvas::asSkCanvas() {
    LOG_ALWAYS_FATAL_IF(!mDisplayList,
            "attempting to get an SkCanvas when we are not recording!");
    if (!mSkiaCanvasProxy) {
        mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
    }

    // SkCanvas instances default to identity transform, but should inherit
    // the state of this Canvas; if this code was in the SkiaCanvasProxy
    // constructor, we couldn't cache mSkiaCanvasProxy.
    SkMatrix parentTransform;
    getMatrix(&parentTransform);
    mSkiaCanvasProxy.get()->setMatrix(parentTransform);

    return mSkiaCanvasProxy.get();
}

// ----------------------------------------------------------------------------
// CanvasStateClient implementation
// ----------------------------------------------------------------------------

void RecordingCanvas::onViewportInitialized() {
}

void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
    if (removed.flags & Snapshot::kFlagIsFboLayer) {
        addOp(alloc().create_trivial<EndLayerOp>());
    } else if (removed.flags & Snapshot::kFlagIsLayer) {
        addOp(alloc().create_trivial<EndUnclippedLayerOp>());
    }
}

// ----------------------------------------------------------------------------
// android/graphics/Canvas state operations
// ----------------------------------------------------------------------------
// Save (layer)
int RecordingCanvas::save(SaveFlags::Flags flags) {
    return mState.save((int) flags);
}

void RecordingCanvas::RecordingCanvas::restore() {
    mState.restore();
}

void RecordingCanvas::restoreToCount(int saveCount) {
    mState.restoreToCount(saveCount);
}

int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
        const SkPaint* paint, SaveFlags::Flags flags) {
    // force matrix/clip isolation for layer
    flags |= SaveFlags::MatrixClip;
    bool clippedLayer = flags & SaveFlags::ClipToLayer;

    const Snapshot& previous = *mState.currentSnapshot();

    // initialize the snapshot as though it almost represents an FBO layer so deferred draw
    // operations will be able to store and restore the current clip and transform info, and
    // quick rejection will be correct (for display lists)

    const Rect unmappedBounds(left, top, right, bottom);

    // determine clipped bounds relative to previous viewport.
    Rect visibleBounds = unmappedBounds;
    previous.transform->mapRect(visibleBounds);

    if (CC_UNLIKELY(!clippedLayer
            && previous.transform->rectToRect()
            && visibleBounds.contains(previous.getRenderTargetClip()))) {
        // unlikely case where an unclipped savelayer is recorded with a clip it can use,
        // as none of its unaffected/unclipped area is visible
        clippedLayer = true;
        flags |= SaveFlags::ClipToLayer;
    }

    visibleBounds.doIntersect(previous.getRenderTargetClip());
    visibleBounds.snapToPixelBoundaries();
    visibleBounds.doIntersect(Rect(previous.getViewportWidth(), previous.getViewportHeight()));

    // Map visible bounds back to layer space, and intersect with parameter bounds
    Rect layerBounds = visibleBounds;
    Matrix4 inverse;
    inverse.loadInverse(*previous.transform);
    inverse.mapRect(layerBounds);
    layerBounds.doIntersect(unmappedBounds);

    int saveValue = mState.save((int) flags);
    Snapshot& snapshot = *mState.writableSnapshot();

    // layerBounds is in original bounds space, but clipped by current recording clip
    if (layerBounds.isEmpty() || unmappedBounds.isEmpty()) {
        // Don't bother recording layer, since it's been rejected
        if (CC_LIKELY(clippedLayer)) {
            snapshot.resetClip(0, 0, 0, 0);
        }
        return saveValue;
    }

    if (CC_LIKELY(clippedLayer)) {
        auto previousClip = getRecordedClip(); // note: done before new snapshot's clip has changed

        snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer;
        snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight());
        snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f);

        Rect clip = layerBounds;
        clip.translate(-unmappedBounds.left, -unmappedBounds.top);
        snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
        snapshot.roundRectClipState = nullptr;

        addOp(alloc().create_trivial<BeginLayerOp>(
                unmappedBounds,
                *previous.transform, // transform to *draw* with
                previousClip, // clip to *draw* with
                refPaint(paint)));
    } else {
        snapshot.flags |= Snapshot::kFlagIsLayer;

        addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
                unmappedBounds,
                *mState.currentSnapshot()->transform,
                getRecordedClip(),
                refPaint(paint)));
    }

    return saveValue;
}

// Matrix
void RecordingCanvas::rotate(float degrees) {
    if (degrees == 0) return;

    mState.rotate(degrees);
}

void RecordingCanvas::scale(float sx, float sy) {
    if (sx == 1 && sy == 1) return;

    mState.scale(sx, sy);
}

void RecordingCanvas::skew(float sx, float sy) {
    mState.skew(sx, sy);
}

void RecordingCanvas::translate(float dx, float dy) {
    if (dx == 0 && dy == 0) return;

    mState.translate(dx, dy, 0);
}

// Clip
bool RecordingCanvas::getClipBounds(SkRect* outRect) const {
    *outRect = mState.getLocalClipBounds().toSkRect();
    return !(outRect->isEmpty());
}
bool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
    return mState.quickRejectConservative(left, top, right, bottom);
}
bool RecordingCanvas::quickRejectPath(const SkPath& path) const {
    SkRect bounds = path.getBounds();
    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
}
bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
    return mState.clipRect(left, top, right, bottom, op);
}
bool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
    return mState.clipPath(path, op);
}
bool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
    return mState.clipRegion(region, op);
}

// ----------------------------------------------------------------------------
// android/graphics/Canvas draw operations
// ----------------------------------------------------------------------------
void RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
    SkPaint paint;
    paint.setColor(color);
    paint.setXfermodeMode(mode);
    drawPaint(paint);
}

void RecordingCanvas::drawPaint(const SkPaint& paint) {
    addOp(alloc().create_trivial<RectOp>(
            mState.getRenderTargetClipBounds(), // OK, since we've not passed transform
            Matrix4::identity(),
            getRecordedClip(),
            refPaint(&paint)));
}

static Rect calcBoundsOfPoints(const float* points, int floatCount) {
    Rect unmappedBounds(points[0], points[1], points[0], points[1]);
    for (int i = 2; i < floatCount; i += 2) {
        unmappedBounds.expandToCover(points[i], points[i + 1]);
    }
    return unmappedBounds;
}

// Geometry
void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPaint& paint) {
    if (floatCount < 2) return;
    floatCount &= ~0x1; // round down to nearest two

    addOp(alloc().create_trivial<PointsOp>(
            calcBoundsOfPoints(points, floatCount),
            *mState.currentSnapshot()->transform,
            getRecordedClip(),
            refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
}

void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) {
    if (floatCount < 4) return;
    floatCount &= ~0x3; // round down to nearest four

    addOp(alloc().create_trivial<LinesOp>(
            calcBoundsOfPoints(points, floatCount),
            *mState.currentSnapshot()->transform,
            getRecordedClip(),
            refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
}

void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
    addOp(alloc().create_trivial<RectOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint)));
}

void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
    if (rects == nullptr) return;

    Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc<Vertex>(vertexCount * sizeof(Vertex));
    Vertex* vertex = rectData;

    float left = FLT_MAX;
    float top = FLT_MAX;
    float right = FLT_MIN;
    float bottom = FLT_MIN;
    for (int index = 0; index < vertexCount; index += 4) {
        float l = rects[index + 0];
        float t = rects[index + 1];
        float r = rects[index + 2];
        float b = rects[index + 3];

        Vertex::set(vertex++, l, t);
        Vertex::set(vertex++, r, t);
        Vertex::set(vertex++, l, b);
        Vertex::set(vertex++, r, b);

        left = std::min(left, l);
        top = std::min(top, t);
        right = std::max(right, r);
        bottom = std::max(bottom, b);
    }
    addOp(alloc().create_trivial<SimpleRectsOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), rectData, vertexCount));
}

void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
    if (paint.getStyle() == SkPaint::kFill_Style
            && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
        int count = 0;
        Vector<float> rects;
        SkRegion::Iterator it(region);
        while (!it.done()) {
            const SkIRect& r = it.rect();
            rects.push(r.fLeft);
            rects.push(r.fTop);
            rects.push(r.fRight);
            rects.push(r.fBottom);
            count += 4;
            it.next();
        }
        drawSimpleRects(rects.array(), count, &paint);
    } else {
        SkRegion::Iterator it(region);
        while (!it.done()) {
            const SkIRect& r = it.rect();
            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
            it.next();
        }
    }
}
void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
            float rx, float ry, const SkPaint& paint) {
    addOp(alloc().create_trivial<RoundRectOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), rx, ry));
}

void RecordingCanvas::drawRoundRect(
        CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
        CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
        CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
        CanvasPropertyPaint* paint) {
    mDisplayList->ref(left);
    mDisplayList->ref(top);
    mDisplayList->ref(right);
    mDisplayList->ref(bottom);
    mDisplayList->ref(rx);
    mDisplayList->ref(ry);
    mDisplayList->ref(paint);
    refBitmapsInShader(paint->value.getShader());
    addOp(alloc().create_trivial<RoundRectPropsOp>(
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            &paint->value,
            &left->value, &top->value, &right->value, &bottom->value,
            &rx->value, &ry->value));
}

void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
    // TODO: move to Canvas.h
    if (radius <= 0) return;
    drawOval(x - radius, y - radius, x + radius, y + radius, paint);
}

void RecordingCanvas::drawCircle(
        CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
        CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
    mDisplayList->ref(x);
    mDisplayList->ref(y);
    mDisplayList->ref(radius);
    mDisplayList->ref(paint);
    refBitmapsInShader(paint->value.getShader());
    addOp(alloc().create_trivial<CirclePropsOp>(
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            &paint->value,
            &x->value, &y->value, &radius->value));
}

void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
    addOp(alloc().create_trivial<OvalOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint)));
}

void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
        float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
    if (fabs(sweepAngle) >= 360.0f) {
        drawOval(left, top, right, bottom, paint);
    } else {
        addOp(alloc().create_trivial<ArcOp>(
                Rect(left, top, right, bottom),
                *(mState.currentSnapshot()->transform),
                getRecordedClip(),
                refPaint(&paint),
                startAngle, sweepAngle, useCenter));
    }
}

void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
    addOp(alloc().create_trivial<PathOp>(
            Rect(path.getBounds()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), refPath(&path)));
}

void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
    mDisplayList->ref(tree);
    addOp(alloc().create_trivial<VectorDrawableOp>(
            tree,
            Rect(tree->getBounds()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip()));
}

// Bitmap-based
void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
    save(SaveFlags::Matrix);
    translate(left, top);
    drawBitmap(&bitmap, paint);
    restore();
}

void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
                            const SkPaint* paint) {
    if (matrix.isIdentity()) {
        drawBitmap(&bitmap, paint);
    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
            && MathUtils::isPositive(matrix.getScaleX())
            && MathUtils::isPositive(matrix.getScaleY())) {
        // SkMatrix::isScaleTranslate() not available in L
        SkRect src;
        SkRect dst;
        bitmap.getBounds(&src);
        matrix.mapRect(&dst, src);
        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
    } else {
        save(SaveFlags::Matrix);
        concat(matrix);
        drawBitmap(&bitmap, paint);
        restore();
    }
}

void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
            float srcRight, float srcBottom, float dstLeft, float dstTop,
            float dstRight, float dstBottom, const SkPaint* paint) {
    if (srcLeft == 0 && srcTop == 0
            && srcRight == bitmap.width()
            && srcBottom == bitmap.height()
            && (srcBottom - srcTop == dstBottom - dstTop)
            && (srcRight - srcLeft == dstRight - dstLeft)) {
        // transform simple rect to rect drawing case into position bitmap ops, since they merge
        save(SaveFlags::Matrix);
        translate(dstLeft, dstTop);
        drawBitmap(&bitmap, paint);
        restore();
    } else {
        addOp(alloc().create_trivial<BitmapRectOp>(
                Rect(dstLeft, dstTop, dstRight, dstBottom),
                *(mState.currentSnapshot()->transform),
                getRecordedClip(),
                refPaint(paint), refBitmap(bitmap),
                Rect(srcLeft, srcTop, srcRight, srcBottom)));
    }
}

void RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
            const float* vertices, const int* colors, const SkPaint* paint) {
    int vertexCount = (meshWidth + 1) * (meshHeight + 1);
    addOp(alloc().create_trivial<BitmapMeshOp>(
            calcBoundsOfPoints(vertices, vertexCount * 2),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), refBitmap(bitmap), meshWidth, meshHeight,
            refBuffer<float>(vertices, vertexCount * 2), // 2 floats per vertex
            refBuffer<int>(colors, vertexCount))); // 1 color per vertex
}

void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& patch,
            float dstLeft, float dstTop, float dstRight, float dstBottom,
            const SkPaint* paint) {
    addOp(alloc().create_trivial<PatchOp>(
            Rect(dstLeft, dstTop, dstRight, dstBottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), refBitmap(bitmap), refPatch(&patch)));
}

// Text
void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int glyphCount,
            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
            float boundsRight, float boundsBottom, float totalAdvance) {
    if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
    positions = refBuffer<float>(positions, glyphCount * 2);

    // TODO: either must account for text shadow in bounds, or record separate ops for text shadows
    addOp(alloc().create_trivial<TextOp>(
            Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), glyphs, positions, glyphCount, x, y));
    drawTextDecorations(x, y, totalAdvance, paint);
}

void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
            float hOffset, float vOffset, const SkPaint& paint) {
    if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
    addOp(alloc().create_trivial<TextOnPathOp>(
            mState.getLocalClipBounds(), // TODO: explicitly define bounds
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
}

void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
    addOp(alloc().create_trivial<BitmapOp>(
            Rect(bitmap->width(), bitmap->height()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), refBitmap(*bitmap)));
}

void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
    auto&& stagingProps = renderNode->stagingProperties();
    RenderNodeOp* op = alloc().create_trivial<RenderNodeOp>(
            Rect(stagingProps.getWidth(), stagingProps.getHeight()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            renderNode);
    int opIndex = addOp(op);
    int childIndex = mDisplayList->addChild(op);

    // update the chunk's child indices
    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
    chunk.endChildIndex = childIndex + 1;

    if (renderNode->stagingProperties().isProjectionReceiver()) {
        // use staging property, since recording on UI thread
        mDisplayList->projectionReceiveIndex = opIndex;
    }
}

void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
    // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
    mDisplayList->ref(layerHandle);

    Layer* layer = layerHandle->backingLayer();
    Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
    totalTransform.multiply(layer->getTransform());

    addOp(alloc().create_trivial<TextureLayerOp>(
            Rect(layer->getWidth(), layer->getHeight()),
            totalTransform,
            getRecordedClip(),
            layer));
}

void RecordingCanvas::callDrawGLFunction(Functor* functor) {
    mDisplayList->functors.push_back(functor);
    addOp(alloc().create_trivial<FunctorOp>(
            mState.getLocalClipBounds(), // TODO: explicitly define bounds
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            functor));
}

size_t RecordingCanvas::addOp(RecordedOp* op) {
    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
    int insertIndex = mDisplayList->ops.size();
    mDisplayList->ops.push_back(op);
    if (mDeferredBarrierType != DeferredBarrierType::None) {
        // op is first in new chunk
        mDisplayList->chunks.emplace_back();
        DisplayList::Chunk& newChunk = mDisplayList->chunks.back();
        newChunk.beginOpIndex = insertIndex;
        newChunk.endOpIndex = insertIndex + 1;
        newChunk.reorderChildren = (mDeferredBarrierType == DeferredBarrierType::OutOfOrder);

        int nextChildIndex = mDisplayList->children.size();
        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
        mDeferredBarrierType = DeferredBarrierType::None;
    } else {
        // standard case - append to existing chunk
        mDisplayList->chunks.back().endOpIndex = insertIndex + 1;
    }
    return insertIndex;
}

void RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
    if (!shader) return;

    // If this paint has an SkShader that has an SkBitmap add
    // it to the bitmap pile
    SkBitmap bitmap;
    SkShader::TileMode xy[2];
    if (shader->isABitmap(&bitmap, nullptr, xy)) {
        refBitmap(bitmap);
        return;
    }
    SkShader::ComposeRec rec;
    if (shader->asACompose(&rec)) {
        refBitmapsInShader(rec.fShaderA);
        refBitmapsInShader(rec.fShaderB);
        return;
    }
}

}; // namespace uirenderer
}; // namespace android
