/*
 * 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 "VectorDrawable.h"

#include <math.h>
#include <string.h>
#include <utils/Log.h>

#include "PathParser.h"
#include "SkColorFilter.h"
#include "SkImageInfo.h"
#include "SkShader.h"
#include "hwui/Paint.h"

#ifdef __ANDROID__
#include "renderthread/RenderThread.h"
#endif

#include "utils/Macros.h"
#include "utils/TraceUtils.h"
#include "utils/VectorDrawableUtils.h"

namespace android {
namespace uirenderer {
namespace VectorDrawable {

const int Tree::MAX_CACHED_BITMAP_SIZE = 2048;

void Path::dump() {
    ALOGD("Path: %s has %zu points", mName.c_str(), mProperties.getData().points.size());
}

// Called from UI thread during the initial setup/theme change.
Path::Path(const char* pathStr, size_t strLength) {
    PathParser::ParseResult result;
    Data data;
    PathParser::getPathDataFromAsciiString(&data, &result, pathStr, strLength);
    mStagingProperties.setData(data);
}

Path::Path(const Path& path) : Node(path) {
    mStagingProperties.syncProperties(path.mStagingProperties);
}

const SkPath& Path::getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) {
    if (useStagingData) {
        tempStagingPath->reset();
        VectorDrawableUtils::verbsToPath(tempStagingPath, mStagingProperties.getData());
        return *tempStagingPath;
    } else {
        if (mSkPathDirty) {
            mSkPath.reset();
            VectorDrawableUtils::verbsToPath(&mSkPath, mProperties.getData());
            mSkPathDirty = false;
        }
        return mSkPath;
    }
}

void Path::syncProperties() {
    if (mStagingPropertiesDirty) {
        mProperties.syncProperties(mStagingProperties);
    } else {
        mStagingProperties.syncProperties(mProperties);
    }
    mStagingPropertiesDirty = false;
}

FullPath::FullPath(const FullPath& path) : Path(path) {
    mStagingProperties.syncProperties(path.mStagingProperties);
}

static void applyTrim(SkPath* outPath, const SkPath& inPath, float trimPathStart, float trimPathEnd,
                      float trimPathOffset) {
    if (trimPathStart == 0.0f && trimPathEnd == 1.0f) {
        *outPath = inPath;
        return;
    }
    outPath->reset();
    if (trimPathStart == trimPathEnd) {
        // Trimmed path should be empty.
        return;
    }
    SkPathMeasure measure(inPath, false);
    float len = SkScalarToFloat(measure.getLength());
    float start = len * fmod((trimPathStart + trimPathOffset), 1.0f);
    float end = len * fmod((trimPathEnd + trimPathOffset), 1.0f);

    if (start > end) {
        measure.getSegment(start, len, outPath, true);
        if (end > 0) {
            measure.getSegment(0, end, outPath, true);
        }
    } else {
        measure.getSegment(start, end, outPath, true);
    }
}

const SkPath& FullPath::getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) {
    if (!useStagingData && !mSkPathDirty && !mProperties.mTrimDirty) {
        return mTrimmedSkPath;
    }
    Path::getUpdatedPath(useStagingData, tempStagingPath);
    SkPath* outPath;
    if (useStagingData) {
        SkPath inPath = *tempStagingPath;
        applyTrim(tempStagingPath, inPath, mStagingProperties.getTrimPathStart(),
                  mStagingProperties.getTrimPathEnd(), mStagingProperties.getTrimPathOffset());
        outPath = tempStagingPath;
    } else {
        if (mProperties.getTrimPathStart() != 0.0f || mProperties.getTrimPathEnd() != 1.0f) {
            mProperties.mTrimDirty = false;
            applyTrim(&mTrimmedSkPath, mSkPath, mProperties.getTrimPathStart(),
                      mProperties.getTrimPathEnd(), mProperties.getTrimPathOffset());
            outPath = &mTrimmedSkPath;
        } else {
            outPath = &mSkPath;
        }
    }
    const FullPathProperties& properties = useStagingData ? mStagingProperties : mProperties;
    bool setFillPath = properties.getFillGradient() != nullptr ||
                       properties.getFillColor() != SK_ColorTRANSPARENT;
    if (setFillPath) {
        outPath->setFillType(static_cast<SkPathFillType>(properties.getFillType()));
    }
    return *outPath;
}

void FullPath::dump() {
    Path::dump();
    ALOGD("stroke width, color, alpha: %f, %d, %f, fill color, alpha: %d, %f",
          mProperties.getStrokeWidth(), mProperties.getStrokeColor(), mProperties.getStrokeAlpha(),
          mProperties.getFillColor(), mProperties.getFillAlpha());
}

inline SkColor applyAlpha(SkColor color, float alpha) {
    int alphaBytes = SkColorGetA(color);
    return SkColorSetA(color, alphaBytes * alpha);
}

void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) {
    const FullPathProperties& properties = useStagingData ? mStagingProperties : mProperties;
    SkPath tempStagingPath;
    const SkPath& renderPath = getUpdatedPath(useStagingData, &tempStagingPath);

    // Draw path's fill, if fill color or gradient is valid
    bool needsFill = false;
    SkPaint paint;
    if (properties.getFillGradient() != nullptr) {
        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
        paint.setShader(sk_sp<SkShader>(SkSafeRef(properties.getFillGradient())));
        needsFill = true;
    } else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
        paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
        needsFill = true;
    }

    if (needsFill) {
        paint.setStyle(SkPaint::Style::kFill_Style);
        paint.setAntiAlias(mAntiAlias);
        outCanvas->drawPath(renderPath, paint);
    }

    // Draw path's stroke, if stroke color or Gradient is valid
    bool needsStroke = false;
    if (properties.getStrokeGradient() != nullptr) {
        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
        paint.setShader(sk_sp<SkShader>(SkSafeRef(properties.getStrokeGradient())));
        needsStroke = true;
    } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
        paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
        needsStroke = true;
    }
    if (needsStroke) {
        paint.setStyle(SkPaint::Style::kStroke_Style);
        paint.setAntiAlias(mAntiAlias);
        paint.setStrokeJoin(SkPaint::Join(properties.getStrokeLineJoin()));
        paint.setStrokeCap(SkPaint::Cap(properties.getStrokeLineCap()));
        paint.setStrokeMiter(properties.getStrokeMiterLimit());
        paint.setStrokeWidth(properties.getStrokeWidth());
        outCanvas->drawPath(renderPath, paint);
    }
}

void FullPath::syncProperties() {
    Path::syncProperties();

    if (mStagingPropertiesDirty) {
        mProperties.syncProperties(mStagingProperties);
    } else {
        // Update staging property with property values from animation.
        mStagingProperties.syncProperties(mProperties);
    }
    mStagingPropertiesDirty = false;
}

REQUIRE_COMPATIBLE_LAYOUT(FullPath::FullPathProperties::PrimitiveFields);

static_assert(sizeof(float) == sizeof(int32_t), "float is not the same size as int32_t");
static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor is not the same size as int32_t");

bool FullPath::FullPathProperties::copyProperties(int8_t* outProperties, int length) const {
    int propertyDataSize = sizeof(FullPathProperties::PrimitiveFields);
    if (length != propertyDataSize) {
        LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
                         propertyDataSize, length);
        return false;
    }

    PrimitiveFields* out = reinterpret_cast<PrimitiveFields*>(outProperties);
    *out = mPrimitiveFields;
    return true;
}

void FullPath::FullPathProperties::setColorPropertyValue(int propertyId, int32_t value) {
    Property currentProperty = static_cast<Property>(propertyId);
    if (currentProperty == Property::strokeColor) {
        setStrokeColor(value);
    } else if (currentProperty == Property::fillColor) {
        setFillColor(value);
    } else {
        LOG_ALWAYS_FATAL(
                "Error setting color property on FullPath: No valid property"
                " with id: %d",
                propertyId);
    }
}

void FullPath::FullPathProperties::setPropertyValue(int propertyId, float value) {
    Property property = static_cast<Property>(propertyId);
    switch (property) {
        case Property::strokeWidth:
            setStrokeWidth(value);
            break;
        case Property::strokeAlpha:
            setStrokeAlpha(value);
            break;
        case Property::fillAlpha:
            setFillAlpha(value);
            break;
        case Property::trimPathStart:
            setTrimPathStart(value);
            break;
        case Property::trimPathEnd:
            setTrimPathEnd(value);
            break;
        case Property::trimPathOffset:
            setTrimPathOffset(value);
            break;
        default:
            LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId);
            break;
    }
}

void ClipPath::draw(SkCanvas* outCanvas, bool useStagingData) {
    SkPath tempStagingPath;
    outCanvas->clipPath(getUpdatedPath(useStagingData, &tempStagingPath));
}

Group::Group(const Group& group) : Node(group) {
    mStagingProperties.syncProperties(group.mStagingProperties);
}

void Group::draw(SkCanvas* outCanvas, bool useStagingData) {
    // Save the current clip and matrix information, which is local to this group.
    SkAutoCanvasRestore saver(outCanvas, true);
    // apply the current group's matrix to the canvas
    SkMatrix stackedMatrix;
    const GroupProperties& prop = useStagingData ? mStagingProperties : mProperties;
    getLocalMatrix(&stackedMatrix, prop);
    outCanvas->concat(stackedMatrix);
    // Draw the group tree in the same order as the XML file.
    for (auto& child : mChildren) {
        child->draw(outCanvas, useStagingData);
    }
    // Restore the previous clip and matrix information.
}

void Group::dump() {
    ALOGD("Group %s has %zu children: ", mName.c_str(), mChildren.size());
    ALOGD("Group translateX, Y : %f, %f, scaleX, Y: %f, %f", mProperties.getTranslateX(),
          mProperties.getTranslateY(), mProperties.getScaleX(), mProperties.getScaleY());
    for (size_t i = 0; i < mChildren.size(); i++) {
        mChildren[i]->dump();
    }
}

void Group::syncProperties() {
    // Copy over the dirty staging properties
    if (mStagingPropertiesDirty) {
        mProperties.syncProperties(mStagingProperties);
    } else {
        mStagingProperties.syncProperties(mProperties);
    }
    mStagingPropertiesDirty = false;
    for (auto& child : mChildren) {
        child->syncProperties();
    }
}

void Group::getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties) {
    outMatrix->reset();
    // TODO: use rotate(mRotate, mPivotX, mPivotY) and scale with pivot point, instead of
    // translating to pivot for rotating and scaling, then translating back.
    outMatrix->postTranslate(-properties.getPivotX(), -properties.getPivotY());
    outMatrix->postScale(properties.getScaleX(), properties.getScaleY());
    outMatrix->postRotate(properties.getRotation(), 0, 0);
    outMatrix->postTranslate(properties.getTranslateX() + properties.getPivotX(),
                             properties.getTranslateY() + properties.getPivotY());
}

void Group::addChild(Node* child) {
    mChildren.emplace_back(child);
    if (mPropertyChangedListener != nullptr) {
        child->setPropertyChangedListener(mPropertyChangedListener);
    }
}

bool Group::GroupProperties::copyProperties(float* outProperties, int length) const {
    int propertyCount = static_cast<int>(Property::count);
    if (length != propertyCount) {
        LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
                         propertyCount, length);
        return false;
    }

    PrimitiveFields* out = reinterpret_cast<PrimitiveFields*>(outProperties);
    *out = mPrimitiveFields;
    return true;
}

// TODO: Consider animating the properties as float pointers
// Called on render thread
float Group::GroupProperties::getPropertyValue(int propertyId) const {
    Property currentProperty = static_cast<Property>(propertyId);
    switch (currentProperty) {
        case Property::rotate:
            return getRotation();
        case Property::pivotX:
            return getPivotX();
        case Property::pivotY:
            return getPivotY();
        case Property::scaleX:
            return getScaleX();
        case Property::scaleY:
            return getScaleY();
        case Property::translateX:
            return getTranslateX();
        case Property::translateY:
            return getTranslateY();
        default:
            LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
            return 0;
    }
}

// Called on render thread
void Group::GroupProperties::setPropertyValue(int propertyId, float value) {
    Property currentProperty = static_cast<Property>(propertyId);
    switch (currentProperty) {
        case Property::rotate:
            setRotation(value);
            break;
        case Property::pivotX:
            setPivotX(value);
            break;
        case Property::pivotY:
            setPivotY(value);
            break;
        case Property::scaleX:
            setScaleX(value);
            break;
        case Property::scaleY:
            setScaleY(value);
            break;
        case Property::translateX:
            setTranslateX(value);
            break;
        case Property::translateY:
            setTranslateY(value);
            break;
        default:
            LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
    }
}

bool Group::isValidProperty(int propertyId) {
    return GroupProperties::isValidProperty(propertyId);
}

bool Group::GroupProperties::isValidProperty(int propertyId) {
    return propertyId >= 0 && propertyId < static_cast<int>(Property::count);
}

int Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds,
               bool needsMirroring, bool canReuseCache) {
    // The imageView can scale the canvas in different ways, in order to
    // avoid blurry scaling, we have to draw into a bitmap with exact pixel
    // size first. This bitmap size is determined by the bounds and the
    // canvas scale.
    SkMatrix canvasMatrix;
    outCanvas->getMatrix(&canvasMatrix);
    float canvasScaleX = 1.0f;
    float canvasScaleY = 1.0f;
    if (canvasMatrix.getSkewX() == 0 && canvasMatrix.getSkewY() == 0) {
        // Only use the scale value when there's no skew or rotation in the canvas matrix.
        // TODO: Add a cts test for drawing VD on a canvas with negative scaling factors.
        canvasScaleX = fabs(canvasMatrix.getScaleX());
        canvasScaleY = fabs(canvasMatrix.getScaleY());
    }
    int scaledWidth = (int)(bounds.width() * canvasScaleX);
    int scaledHeight = (int)(bounds.height() * canvasScaleY);
    scaledWidth = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledWidth);
    scaledHeight = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledHeight);

    if (scaledWidth <= 0 || scaledHeight <= 0) {
        return 0;
    }

    mStagingProperties.setScaledSize(scaledWidth, scaledHeight);
    int saveCount = outCanvas->save(SaveFlags::MatrixClip);
    outCanvas->translate(bounds.fLeft, bounds.fTop);

    // Handle RTL mirroring.
    if (needsMirroring) {
        outCanvas->translate(bounds.width(), 0);
        outCanvas->scale(-1.0f, 1.0f);
    }
    mStagingProperties.setColorFilter(colorFilter);

    // At this point, canvas has been translated to the right position.
    // And we use this bound for the destination rect for the drawBitmap, so
    // we offset to (0, 0);
    SkRect tmpBounds = bounds;
    tmpBounds.offsetTo(0, 0);
    mStagingProperties.setBounds(tmpBounds);
    outCanvas->drawVectorDrawable(this);
    outCanvas->restoreToCount(saveCount);
    return scaledWidth * scaledHeight;
}

void Tree::drawStaging(Canvas* outCanvas) {
    bool redrawNeeded = allocateBitmapIfNeeded(mStagingCache, mStagingProperties.getScaledWidth(),
                                               mStagingProperties.getScaledHeight());
    // draw bitmap cache
    if (redrawNeeded || mStagingCache.dirty) {
        updateBitmapCache(*mStagingCache.bitmap, true);
        mStagingCache.dirty = false;
    }

    SkPaint skp;
    getPaintFor(&skp, mStagingProperties);
    Paint paint;
    paint.setFilterQuality(skp.getFilterQuality());
    paint.setColorFilter(skp.refColorFilter());
    paint.setAlpha(skp.getAlpha());
    outCanvas->drawBitmap(*mStagingCache.bitmap, 0, 0, mStagingCache.bitmap->width(),
                          mStagingCache.bitmap->height(), mStagingProperties.getBounds().left(),
                          mStagingProperties.getBounds().top(),
                          mStagingProperties.getBounds().right(),
                          mStagingProperties.getBounds().bottom(), &paint);
}

void Tree::getPaintFor(SkPaint* outPaint, const TreeProperties& prop) const {
    // HWUI always draws VD with bilinear filtering.
    outPaint->setFilterQuality(kLow_SkFilterQuality);
    if (prop.getColorFilter() != nullptr) {
        outPaint->setColorFilter(sk_ref_sp(prop.getColorFilter()));
    }
    outPaint->setAlpha(prop.getRootAlpha() * 255);
}

Bitmap& Tree::getBitmapUpdateIfDirty() {
    bool redrawNeeded = allocateBitmapIfNeeded(mCache, mProperties.getScaledWidth(),
                                               mProperties.getScaledHeight());
    if (redrawNeeded || mCache.dirty) {
        updateBitmapCache(*mCache.bitmap, false);
        mCache.dirty = false;
    }
    return *mCache.bitmap;
}

void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
    if (canvas->quickReject(bounds)) {
        // The RenderNode is on screen, but the AVD is not.
        return;
    }

    // Update the paint for any animatable properties
    SkPaint paint = inPaint;
    paint.setAlpha(mProperties.getRootAlpha() * 255);

    Bitmap& bitmap = getBitmapUpdateIfDirty();
    SkBitmap skiaBitmap;
    bitmap.getSkBitmap(&skiaBitmap);

    int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
    int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
    canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight), bounds,
                           &paint, SkCanvas::kFast_SrcRectConstraint);
}

void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) {
    SkBitmap outCache;
    bitmap.getSkBitmap(&outCache);
    int cacheWidth = outCache.width();
    int cacheHeight = outCache.height();
    ATRACE_FORMAT("VectorDrawable repaint %dx%d", cacheWidth, cacheHeight);
    outCache.eraseColor(SK_ColorTRANSPARENT);
    SkCanvas outCanvas(outCache);
    float viewportWidth =
            useStagingData ? mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
    float viewportHeight = useStagingData ? mStagingProperties.getViewportHeight()
                                          : mProperties.getViewportHeight();
    float scaleX = cacheWidth / viewportWidth;
    float scaleY = cacheHeight / viewportHeight;
    outCanvas.scale(scaleX, scaleY);
    mRootNode->draw(&outCanvas, useStagingData);
}

bool Tree::allocateBitmapIfNeeded(Cache& cache, int width, int height) {
    if (!canReuseBitmap(cache.bitmap.get(), width, height)) {
        SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType);
        cache.bitmap = Bitmap::allocateHeapBitmap(info);
        return true;
    }
    return false;
}

bool Tree::canReuseBitmap(Bitmap* bitmap, int width, int height) {
    return bitmap && width <= bitmap->width() && height <= bitmap->height();
}

void Tree::onPropertyChanged(TreeProperties* prop) {
    if (prop == &mStagingProperties) {
        mStagingCache.dirty = true;
    } else {
        mCache.dirty = true;
    }
}

class MinMaxAverage {
public:
    void add(float sample) {
        if (mCount == 0) {
            mMin = sample;
            mMax = sample;
        } else {
            mMin = std::min(mMin, sample);
            mMax = std::max(mMax, sample);
        }
        mTotal += sample;
        mCount++;
    }

    float average() { return mTotal / mCount; }

    float min() { return mMin; }

    float max() { return mMax; }

    float delta() { return mMax - mMin; }

private:
    float mMin = 0.0f;
    float mMax = 0.0f;
    float mTotal = 0.0f;
    int mCount = 0;
};

BitmapPalette Tree::computePalette() {
    // TODO Cache this and share the code with Bitmap.cpp

    ATRACE_CALL();

    // TODO: This calculation of converting to HSV & tracking min/max is probably overkill
    // Experiment with something simpler since we just want to figure out if it's "color-ful"
    // and then the average perceptual lightness.

    MinMaxAverage hue, saturation, value;
    int sampledCount = 0;

    // Sample a grid of 100 pixels to get an overall estimation of the colors in play
    mRootNode->forEachFillColor([&](SkColor color) {
        if (SkColorGetA(color) < 75) {
            return;
        }
        sampledCount++;
        float hsv[3];
        SkColorToHSV(color, hsv);
        hue.add(hsv[0]);
        saturation.add(hsv[1]);
        value.add(hsv[2]);
    });

    if (sampledCount == 0) {
        ALOGV("VectorDrawable is mostly translucent");
        return BitmapPalette::Unknown;
    }

    ALOGV("samples = %d, hue [min = %f, max = %f, avg = %f]; saturation [min = %f, max = %f, avg = "
          "%f]; value [min = %f, max = %f, avg = %f]",
          sampledCount, hue.min(), hue.max(), hue.average(), saturation.min(), saturation.max(),
          saturation.average(), value.min(), value.max(), value.average());

    if (hue.delta() <= 20 && saturation.delta() <= .1f) {
        if (value.average() >= .5f) {
            return BitmapPalette::Light;
        } else {
            return BitmapPalette::Dark;
        }
    }
    return BitmapPalette::Unknown;
}

}  // namespace VectorDrawable

}  // namespace uirenderer
}  // namespace android
