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

#include "modules/skresources/src/SkAnimCodecPlayer.h"

#include "include/codec/SkCodec.h"
#include "include/codec/SkEncodedOrigin.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"
#include "src/codec/SkCodecImageGenerator.h"

#include <algorithm>
#include <cstddef>
#include <memory>
#include <utility>
#include <vector>

SkAnimCodecPlayer::SkAnimCodecPlayer(std::unique_ptr<SkCodec> codec) : fCodec(std::move(codec)) {
    fImageInfo = fCodec->getInfo();
    fFrameInfos = fCodec->getFrameInfo();
    fImages.resize(fFrameInfos.size());

    // change the interpretation of fDuration to a end-time for that frame
    size_t dur = 0;
    for (auto& f : fFrameInfos) {
        dur += f.fDuration;
        f.fDuration = dur;
    }
    fTotalDuration = dur;

    if (!fTotalDuration) {
        // Static image -- may or may not have returned a single frame info.
        fFrameInfos.clear();
        fImages.clear();
        fImages.push_back(SkImages::DeferredFromGenerator(
                SkCodecImageGenerator::MakeFromCodec(std::move(fCodec))));
    }
}

SkAnimCodecPlayer::~SkAnimCodecPlayer() {}

SkISize SkAnimCodecPlayer::dimensions() const {
    if (!fCodec) {
        auto image = fImages.front();
        return image ? image->dimensions() : SkISize::MakeEmpty();
    }
    if (SkEncodedOriginSwapsWidthHeight(fCodec->getOrigin())) {
        return { fImageInfo.height(), fImageInfo.width() };
    }
    return { fImageInfo.width(), fImageInfo.height() };
}

sk_sp<SkImage> SkAnimCodecPlayer::getFrameAt(int index) {
    SkASSERT((unsigned)index < fFrameInfos.size());

    if (fImages[index]) {
        return fImages[index];
    }

    size_t rb = fImageInfo.minRowBytes();
    size_t size = fImageInfo.computeByteSize(rb);
    auto data = SkData::MakeUninitialized(size);

    SkCodec::Options opts;
    opts.fFrameIndex = index;

    const auto origin = fCodec->getOrigin();
    const auto orientedDims = this->dimensions();
    const auto originMatrix = SkEncodedOriginToMatrix(origin, orientedDims.width(),
                                                              orientedDims.height());

    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);

    auto imageInfo = fImageInfo;
    if (fFrameInfos[index].fAlphaType != kOpaque_SkAlphaType && imageInfo.isOpaque()) {
        imageInfo = imageInfo.makeAlphaType(kPremul_SkAlphaType);
    }
    const int requiredFrame = fFrameInfos[index].fRequiredFrame;
    if (requiredFrame != SkCodec::kNoFrame && fImages[requiredFrame]) {
        auto requiredImage = fImages[requiredFrame];
        auto canvas = SkCanvas::MakeRasterDirect(imageInfo, data->writable_data(), rb);
        if (origin != kDefault_SkEncodedOrigin) {
            // The required frame is stored after applying the origin. Undo that,
            // because the codec decodes prior to applying the origin.
            // FIXME: Another approach would be to decode the frame's delta on top
            // of transparent black, and then draw that through the origin matrix
            // onto the required frame. To do that, SkCodec needs to expose the
            // rectangle of the delta and the blend mode, so we can handle
            // kRestoreBGColor frames and Blend::kSrc.
            SkMatrix inverse;
            SkAssertResult(originMatrix.invert(&inverse));
            canvas->concat(inverse);
        }
        canvas->drawImage(requiredImage, 0, 0, SkSamplingOptions(), &paint);
        opts.fPriorFrame = requiredFrame;
    }

    if (SkCodec::kSuccess != fCodec->getPixels(imageInfo, data->writable_data(), rb, &opts)) {
        return nullptr;
    }

    auto image = SkImages::RasterFromData(imageInfo, std::move(data), rb);
    if (origin != kDefault_SkEncodedOrigin) {
        imageInfo = imageInfo.makeDimensions(orientedDims);
        rb = imageInfo.minRowBytes();
        size = imageInfo.computeByteSize(rb);
        data = SkData::MakeUninitialized(size);
        auto canvas = SkCanvas::MakeRasterDirect(imageInfo, data->writable_data(), rb);
        canvas->concat(originMatrix);
        canvas->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
        image = SkImages::RasterFromData(imageInfo, std::move(data), rb);
    }
    return fImages[index] = image;
}

sk_sp<SkImage> SkAnimCodecPlayer::getFrame() {
    SkASSERT(fTotalDuration > 0 || fImages.size() == 1);

    return fTotalDuration > 0
        ? this->getFrameAt(fCurrIndex)
        : fImages.front();
}

bool SkAnimCodecPlayer::seek(uint32_t msec) {
    if (!fTotalDuration) {
        return false;
    }

    msec %= fTotalDuration;

    auto lower = std::lower_bound(fFrameInfos.begin(), fFrameInfos.end(), msec,
                                  [](const SkCodec::FrameInfo& info, uint32_t msec) {
                                      return (uint32_t)info.fDuration <= msec;
                                  });
    int prevIndex = fCurrIndex;
    fCurrIndex = lower - fFrameInfos.begin();
    return fCurrIndex != prevIndex;
}


