// Copyright (C) 2019 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.

#pragma once
#include "aemu/base/files/Stream.h"

#include <stddef.h>
#include <list>
#include <vector>

namespace android {
namespace emulation {

class MediaSnapshotHelper;

class MediaSnapshotState {
public:
    struct ColorAspects {
        unsigned int primaries;
        unsigned int range;
        unsigned int transfer;
        unsigned int space;
    };

    struct PacketInfo {
        std::vector<uint8_t> data;
        uint64_t pts;
    };

    struct FrameInfo {
        std::vector<uint8_t> data;
        std::vector<uint32_t> texture;
        int width;
        int height;
        uint64_t pts;
        ColorAspects color;
    };

    bool savePacket(std::vector<uint8_t> data, uint64_t pts = 0);
    void saveSps(std::vector<uint8_t> xsps) { sps = std::move(xsps); }
    void savePps(std::vector<uint8_t> xpps) { pps = std::move(xpps); }

    void saveDecodedFrame(std::vector<uint8_t> data,
                          int width = 0,
                          int height = 0,
                          uint64_t pts = 0,
                          ColorAspects xcolor = ColorAspects{});

    void saveDecodedFrame(std::vector<uint32_t> texture,
                          int width = 0,
                          int height = 0,
                          uint64_t pts = 0,
                          ColorAspects xcolor = ColorAspects{});

    void saveDecodedFrame(FrameInfo frame) {
        savedFrames.push_back(std::move(frame));
    }

    void save(base::Stream* stream) const;
    void load(base::Stream* stream);

    FrameInfo* frontFrame() {
        if (savedFrames.empty()) {
            return nullptr;
        }
        return &(savedFrames.front());
    }

    void discardFrontFrame() {
        if (!savedFrames.empty()) {
            savedFrames.pop_front();
        }
    }

    friend MediaSnapshotHelper;

private:
    std::vector<uint8_t> sps;  // sps NALU
    std::vector<uint8_t> pps;  // pps NALU
    std::vector<PacketInfo> savedPackets;
    FrameInfo savedDecodedFrame;  // only one or nothing
    std::list<FrameInfo> savedFrames;

private:
    bool savePacket(const uint8_t* frame, size_t size, uint64_t pts = 0);

    //    void saveVec(base::Stream* stream, const std::vector<uint8_t>& vec)
    //    const;

    void saveFrameInfo(base::Stream* stream, const FrameInfo& frame) const;

    void savePacketInfo(base::Stream* stream, const PacketInfo& pkt) const;
    void saveColor(base::Stream* stream, const ColorAspects& color) const;

    void loadFrameInfo(base::Stream* stream, FrameInfo& frame);

    void loadPacketInfo(base::Stream* stream, PacketInfo& pkt);

    void loadColor(base::Stream* stream, ColorAspects& color) const;

    //    void loadVec(base::Stream* stream, std::vector<uint8_t>& vec);
};

}  // namespace emulation
}  // namespace android
