/*
 * Copyright (C) 2020 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 "SerializedFlushToState.h"

#include <limits>

#include <android-base/logging.h>

SerializedFlushToState::SerializedFlushToState(uint64_t start, LogMask log_mask,
                                               std::list<SerializedLogChunk>* logs)
    : FlushToState(start, log_mask), logs_(logs) {
    log_id_for_each(i) {
        if (((1 << i) & log_mask) == 0) {
            continue;
        }
        logs_needed_from_next_position_[i] = true;
    }
}

SerializedFlushToState::~SerializedFlushToState() {
    log_id_for_each(i) {
        if (log_positions_[i]) {
            log_positions_[i]->buffer_it->DetachReader(this);
        }
    }
}

void SerializedFlushToState::CreateLogPosition(log_id_t log_id) {
    CHECK(!logs_[log_id].empty());
    LogPosition log_position;
    auto it = logs_[log_id].begin();
    while (it != logs_[log_id].end() && start() > it->highest_sequence_number()) {
        ++it;
    }
    if (it == logs_[log_id].end()) {
        --it;
    }
    it->AttachReader(this);
    log_position.buffer_it = it;

    // Find the offset of the first log with sequence number >= start().
    int read_offset = 0;
    while (read_offset < it->write_offset()) {
        const auto* entry = it->log_entry(read_offset);
        if (entry->sequence() >= start()) {
            break;
        }
        read_offset += entry->total_len();
    }
    log_position.read_offset = read_offset;

    log_positions_[log_id].emplace(log_position);
}

void SerializedFlushToState::UpdateLogsNeeded(log_id_t log_id) {
    auto& buffer_it = log_positions_[log_id]->buffer_it;
    auto read_offset = log_positions_[log_id]->read_offset;

    // If there is another log to read in this buffer, let it be read.
    if (read_offset < buffer_it->write_offset()) {
        logs_needed_from_next_position_[log_id] = false;
    } else if (read_offset == buffer_it->write_offset()) {
        // If there are no more logs to read in this buffer and it's the last buffer, then
        // set logs_needed_from_next_position_ to wait until more logs get logged.
        if (buffer_it == std::prev(logs_[log_id].end())) {
            logs_needed_from_next_position_[log_id] = true;
        } else {
            // Otherwise, if there is another buffer piece, move to that and do the same check.
            buffer_it->DetachReader(this);
            ++buffer_it;
            buffer_it->AttachReader(this);
            log_positions_[log_id]->read_offset = 0;
            if (buffer_it->write_offset() == 0) {
                logs_needed_from_next_position_[log_id] = true;
            } else {
                logs_needed_from_next_position_[log_id] = false;
            }
        }
    } else {
        // read_offset > buffer_it->write_offset() should never happen.
        LOG(FATAL) << "read_offset (" << read_offset << ") > buffer_it->write_offset() ("
                   << buffer_it->write_offset() << ")";
    }
}

void SerializedFlushToState::CheckForNewLogs() {
    log_id_for_each(i) {
        if (!logs_needed_from_next_position_[i]) {
            continue;
        }
        if (!log_positions_[i]) {
            if (logs_[i].empty()) {
                continue;
            }
            CreateLogPosition(i);
        }
        UpdateLogsNeeded(i);
    }
}

bool SerializedFlushToState::HasUnreadLogs() {
    CheckForNewLogs();
    log_id_for_each(i) {
        if (log_positions_[i] && !logs_needed_from_next_position_[i]) {
            return true;
        }
    }
    return false;
}

LogWithId SerializedFlushToState::PopNextUnreadLog() {
    uint64_t min_sequence = std::numeric_limits<uint64_t>::max();
    log_id_t log_id;
    const SerializedLogEntry* entry = nullptr;
    log_id_for_each(i) {
        if (!log_positions_[i] || logs_needed_from_next_position_[i]) {
            continue;
        }
        if (log_positions_[i]->log_entry()->sequence() < min_sequence) {
            log_id = i;
            entry = log_positions_[i]->log_entry();
            min_sequence = entry->sequence();
        }
    }
    CHECK_NE(nullptr, entry);

    log_positions_[log_id]->read_offset += entry->total_len();

    logs_needed_from_next_position_[log_id] = true;

    return {log_id, entry};
}

void SerializedFlushToState::Prune(log_id_t log_id) {
    CHECK(log_positions_[log_id].has_value());

    // Decrease the ref count since we're deleting our reference.
    log_positions_[log_id]->buffer_it->DetachReader(this);

    // Delete in the reference.
    log_positions_[log_id].reset();

    // Finally set logs_needed_from_next_position_, so CheckForNewLogs() will re-create the
    // log_position_ object during the next read.
    logs_needed_from_next_position_[log_id] = true;
}
