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

#include "SkData.h"
#include "SkMakeUnique.h"
#include "SkOSPath.h"
#include "SkStream.h"
#include "SkStreamBuffer.h"

#include "FakeStreams.h"
#include "Test.h"

static const char* gText = "Four score and seven years ago";

static void test_get_data_at_position(skiatest::Reporter* r, SkStreamBuffer* buffer, size_t position,
                                    size_t length) {
    sk_sp<SkData> data = buffer->getDataAtPosition(position, length);
    REPORTER_ASSERT(r, data);
    if (data) {
        REPORTER_ASSERT(r, !memcmp(data->data(), gText + position, length));
    }
}

// Test buffering from the beginning, by different amounts.
static void test_buffer_from_beginning(skiatest::Reporter* r, std::unique_ptr<SkStream> stream,
                                       size_t length) {
    if (!stream) {
        return;
    }
    SkStreamBuffer buffer(std::move(stream));

    // Buffer an arbitrary amount:
    size_t buffered = length / 2;
    REPORTER_ASSERT(r, buffer.buffer(buffered));
    REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, buffered));

    // Buffering less is free:
    REPORTER_ASSERT(r, buffer.buffer(buffered / 2));

    // Buffer more should succeed:
    REPORTER_ASSERT(r, buffer.buffer(length));
    REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, length));
}

// Test flushing the stream as we read.
static void test_flushing(skiatest::Reporter* r, std::unique_ptr<SkStream> stream, size_t length,
                          bool getDataAtPosition) {
    if (!stream) {
        return;
    }
    SkStreamBuffer buffer(std::move(stream));
    const size_t step = 5;
    for (size_t position = 0; position + step <= length; position += step) {
        REPORTER_ASSERT(r, buffer.buffer(step));
        REPORTER_ASSERT(r, buffer.markPosition() == position);

        if (!getDataAtPosition) {
            REPORTER_ASSERT(r, !memcmp(buffer.get(), gText + position, step));
        }
        buffer.flush();
    }

    REPORTER_ASSERT(r, !buffer.buffer(step));

    if (getDataAtPosition) {
        for (size_t position = 0; position + step <= length; position += step) {
            test_get_data_at_position(r, &buffer, position, step);
        }
    }
}

DEF_TEST(StreamBuffer, r) {
    const size_t size = strlen(gText);
    sk_sp<SkData> data(SkData::MakeWithoutCopy(gText, size));

    SkString tmpDir = skiatest::GetTmpDir();
    const char* subdir = "streamBuffer.txt";
    SkString path;

    if (!tmpDir.isEmpty()) {
        path = SkOSPath::Join(tmpDir.c_str(), subdir);
        SkFILEWStream writer(path.c_str());
        if (!writer.isValid()) {
            ERRORF(r, "unable to write to '%s'\n", path.c_str());
            return;
        }
        writer.write(gText, size);
    }

    struct {
        std::function<std::unique_ptr<SkStream>()>  createStream;
        bool                                        skipIfNoTmpDir;
    } factories[] = {
        { [&data]() { return skstd::make_unique<SkMemoryStream>(data); },       false  },
        { [&data]() { return skstd::make_unique<NotAssetMemStream>(data); },    false  },
        { [&path]() { return path.isEmpty()
                             ? nullptr
                             : skstd::make_unique<SkFILEStream>(path.c_str()); }, true },
    };

    for (auto f : factories) {
        if (tmpDir.isEmpty() && f.skipIfNoTmpDir) {
            continue;
        }
        test_buffer_from_beginning(r, f.createStream(), size);
        test_flushing(r, f.createStream(), size, false);
        test_flushing(r, f.createStream(), size, true);
    }

    // Stream that will receive more data. Will be owned by the SkStreamBuffer.
    auto halting = skstd::make_unique<HaltingStream>(data, 6);
    HaltingStream* peekHalting = halting.get();
    SkStreamBuffer buffer(std::move(halting));

    // Can only buffer less than what's available (6).
    REPORTER_ASSERT(r, !buffer.buffer(7));
    REPORTER_ASSERT(r, buffer.buffer(5));
    REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, 5));

    // Add some more data. We can buffer and read all of it.
    peekHalting->addNewData(8);
    REPORTER_ASSERT(r, buffer.buffer(14));
    REPORTER_ASSERT(r, !memcmp(buffer.get(), gText, 14));

    // Flush the buffer, which moves the position.
    buffer.flush();

    // Add some data, and try to read more. Can only read what is
    // available.
    peekHalting->addNewData(9);
    REPORTER_ASSERT(r, !buffer.buffer(13));
    peekHalting->addNewData(4);
    REPORTER_ASSERT(r, buffer.buffer(13));

    // Do not call get on this data. We'll come back to this data after adding
    // more.
    buffer.flush();
    const size_t remaining = size - 27;
    REPORTER_ASSERT(r, remaining > 0);
    peekHalting->addNewData(remaining);
    REPORTER_ASSERT(r, buffer.buffer(remaining));
    REPORTER_ASSERT(r, !memcmp(buffer.get(), gText + 27, remaining));

    // Now go back to the data we skipped.
    test_get_data_at_position(r, &buffer, 14, 13);
}
