/*
 * Copyright (C) 2018 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 <string.h>

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

#include <android-base/logging.h>

#include "fdevent/fdevent.h"
#include "sysdeps/uio.h"

// Essentially std::vector<char>, except without zero initialization or reallocation.
struct Block {
    using iterator = char*;

    Block() = default;

    explicit Block(size_t size) { allocate(size); }

    template <typename Iterator>
    Block(Iterator begin, Iterator end) : Block(end - begin) {
        std::copy(begin, end, data_.get());
    }

    Block(const Block& copy) = delete;
    Block(Block&& move) noexcept
        : data_(std::exchange(move.data_, nullptr)),
          capacity_(std::exchange(move.capacity_, 0)),
          size_(std::exchange(move.size_, 0)) {}

    Block& operator=(const Block& copy) = delete;
    Block& operator=(Block&& move) noexcept {
        clear();
        data_ = std::exchange(move.data_, nullptr);
        capacity_ = std::exchange(move.capacity_, 0);
        size_ = std::exchange(move.size_, 0);
        return *this;
    }

    ~Block() = default;

    void resize(size_t new_size) {
        if (!data_) {
            allocate(new_size);
        } else {
            CHECK_GE(capacity_, new_size);
            size_ = new_size;
        }
    }

    template <typename InputIt>
    void assign(InputIt begin, InputIt end) {
        clear();
        allocate(end - begin);
        std::copy(begin, end, data_.get());
    }

    void clear() {
        data_.reset();
        capacity_ = 0;
        size_ = 0;
    }

    size_t capacity() const { return capacity_; }
    size_t size() const { return size_; }
    bool empty() const { return size() == 0; }

    char* data() { return data_.get(); }
    const char* data() const { return data_.get(); }

    char* begin() { return data_.get(); }
    const char* begin() const { return data_.get(); }

    char* end() { return data() + size_; }
    const char* end() const { return data() + size_; }

    char& operator[](size_t idx) { return data()[idx]; }
    const char& operator[](size_t idx) const { return data()[idx]; }

    bool operator==(const Block& rhs) const {
        static_assert(std::is_standard_layout<decltype(data())>());
        return size() == rhs.size() && memcmp(data(), rhs.data(), size()) == 0;
    }

  private:
    void allocate(size_t size) {
        CHECK(data_ == nullptr);
        CHECK_EQ(0ULL, capacity_);
        CHECK_EQ(0ULL, size_);
        if (size != 0) {
            // This isn't std::make_unique because that's equivalent to `new char[size]()`, which
            // value-initializes the array instead of leaving it uninitialized. As an optimization,
            // call new without parentheses to avoid this costly initialization.
            data_.reset(new char[size]);
            capacity_ = size;
            size_ = size;
        }
    }

    std::unique_ptr<char[]> data_;
    size_t capacity_ = 0;
    size_t size_ = 0;
};

struct amessage {
    uint32_t command;     /* command identifier constant      */
    uint32_t arg0;        /* first argument                   */
    uint32_t arg1;        /* second argument                  */
    uint32_t data_length; /* length of payload (0 is allowed) */
    uint32_t data_check;  /* checksum of data payload         */
    uint32_t magic;       /* command ^ 0xffffffff             */
};

struct apacket {
    using payload_type = Block;
    amessage msg;
    payload_type payload;
};

struct IOVector {
    using value_type = char;
    using block_type = Block;
    using size_type = size_t;

    IOVector() = default;

    explicit IOVector(block_type&& block) { append(std::move(block)); }

    IOVector(const IOVector& copy) = delete;
    IOVector(IOVector&& move) noexcept : IOVector() { *this = std::move(move); }

    IOVector& operator=(const IOVector& copy) = delete;
    IOVector& operator=(IOVector&& move) noexcept;

    const value_type* front_data() const {
        if (chain_.empty()) {
            return nullptr;
        }

        return chain_[start_index_].data() + begin_offset_;
    }

    size_type front_size() const {
        if (chain_.empty()) {
            return 0;
        }

        return chain_[start_index_].size() - begin_offset_;
    }

    size_type size() const { return chain_length_ - begin_offset_; }
    bool empty() const { return size() == 0; }

    // Return the last block so the caller can still reuse its allocated capacity
    // or it can be simply ignored.
    block_type clear();

    void drop_front(size_type len);

    // Split the first |len| bytes out of this chain into its own.
    IOVector take_front(size_type len);

    // Add a nonempty block to the chain.
    void append(block_type&& block) {
        if (block.size() == 0) {
            return;
        }
        CHECK_NE(0ULL, block.size());
        chain_length_ += block.size();
        chain_.emplace_back(std::move(block));
    }

    void trim_front();

  private:
    void trim_chain_front();

    // Drop the front block from the chain, and update chain_length_ appropriately.
    void pop_front_block();

    // Iterate over the blocks with a callback with an operator()(const char*, size_t).
    template <typename Fn>
    void iterate_blocks(Fn&& callback) const {
        if (size() == 0) {
            return;
        }

        for (size_t i = start_index_; i < chain_.size(); ++i) {
            const auto& block = chain_[i];
            const char* begin = block.data();
            size_t length = block.size();

            if (i == start_index_) {
                CHECK_GE(block.size(), begin_offset_);
                begin += begin_offset_;
                length -= begin_offset_;
            }
            callback(begin, length);
        }
    }

  public:
    // Copy all of the blocks into a single block.
    template <typename CollectionType = block_type>
    CollectionType coalesce() const& {
        CollectionType result;
        if (size() == 0) {
            return result;
        }

        result.resize(size());

        size_t offset = 0;
        iterate_blocks([&offset, &result](const char* data, size_t len) {
            static_assert(std::is_standard_layout<decltype(result)>());
            memcpy(&result[offset], data, len);
            offset += len;
        });

        return result;
    }

    block_type coalesce() &&;

    template <typename FunctionType>
    auto coalesced(FunctionType&& f) const {
        if (chain_.size() == start_index_ + 1) {
            // If we only have one block, we can use it directly.
            return f(chain_[start_index_].data() + begin_offset_, size());
        } else {
            // Otherwise, copy to a single block.
            auto data = coalesce();
            return f(data.data(), data.size());
        }
    }

    // Get a list of iovecs that can be used to write out all of the blocks.
    std::vector<adb_iovec> iovecs() const;

  private:
    // Total length of all of the blocks in the chain.
    size_t chain_length_ = 0;

    size_t begin_offset_ = 0;
    size_t start_index_ = 0;
    std::vector<block_type> chain_;
};

// An implementation of weak pointers tied to the fdevent run loop.
//
// This allows for code to submit a request for an object, and upon receiving
// a response, know whether the object is still alive, or has been destroyed
// because of other reasons. We keep a list of living weak_ptrs in each object,
// and clear the weak_ptrs when the object is destroyed. This is safe, because
// we require that both the destructor of the referent and the get method on
// the weak_ptr are executed on the main thread.
template <typename T>
struct enable_weak_from_this;

template <typename T>
struct weak_ptr {
    weak_ptr() = default;
    explicit weak_ptr(T* ptr) { reset(ptr); }
    weak_ptr(const weak_ptr& copy) { reset(copy.get()); }

    weak_ptr(weak_ptr&& move) {
        reset(move.get());
        move.reset();
    }

    ~weak_ptr() { reset(); }

    weak_ptr& operator=(const weak_ptr& copy) {
        if (&copy == this) {
            return *this;
        }

        reset(copy.get());
        return *this;
    }

    weak_ptr& operator=(weak_ptr&& move) {
        if (&move == this) {
            return *this;
        }

        reset(move.get());
        move.reset();
        return *this;
    }

    T* get() const {
        fdevent_check_looper();
        return ptr_;
    }

    void reset(T* ptr = nullptr) {
        fdevent_check_looper();

        if (ptr == ptr_) {
            return;
        }

        if (ptr_) {
            ptr_->weak_ptrs_.erase(
                    std::remove(ptr_->weak_ptrs_.begin(), ptr_->weak_ptrs_.end(), this));
        }

        ptr_ = ptr;
        if (ptr_) {
            ptr_->weak_ptrs_.push_back(this);
        }
    }

  private:
    friend struct enable_weak_from_this<T>;
    T* ptr_ = nullptr;
};

template <typename T>
struct enable_weak_from_this {
    ~enable_weak_from_this() {
        if (!weak_ptrs_.empty()) {
            fdevent_check_looper();
            for (auto& weak : weak_ptrs_) {
                weak->ptr_ = nullptr;
            }
            weak_ptrs_.clear();
        }
    }

    weak_ptr<T> weak() { return weak_ptr<T>(static_cast<T*>(this)); }

    void schedule_deletion() {
        fdevent_run_on_looper([this]() { delete static_cast<T*>(this); });
    }

  private:
    friend struct weak_ptr<T>;
    std::vector<weak_ptr<T>*> weak_ptrs_;
};
