/*
    SPDX-FileCopyrightText: 2008 Friedrich W. H. Kossebau <kossebau@kde.org>

    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/

#ifndef KPIECETABLE_PIECETABLE_HPP
#define KPIECETABLE_PIECETABLE_HPP

// lib
#include "piecelist.hpp"
// Qt
#include <QLinkedList>

namespace KPieceTable {

class PieceTable
{
public:
    explicit PieceTable(Size size = 0);
    PieceTable(const PieceTable&) = delete;
    PieceTable(PieceTable&&) = delete;

    ~PieceTable();

    PieceTable& operator=(const PieceTable&) = delete;
    PieceTable& operator=(PieceTable&&) = delete;

public:
    void init(Size size);
    void insert(Address insertDataOffset, Size insertLength, Address storageOffset);
    /// for use to reapply
    void insert(Address insertDataOffset, const PieceList& insertPieceList);
    PieceList remove(const AddressRange& removeRange);
    PieceList replace(const AddressRange& removeRange,
                      Size insertLength, Address storageOffset);
    /// for use to reapply
    void replace(const AddressRange& removeRange, const PieceList& insertPieceList);
    void swap(Address firstStart, const AddressRange& secondRange);
    Piece replaceOne(Address dataOffset, Address storageOffset, Piece::StorageType storageId = Piece::ChangeStorage);

//     int fill( const char FillChar, unsigned int Pos = 0, int Length = -1 ); TODO: filter change, calculated

public:
    [[nodiscard]]
    bool getStorageData(Piece::StorageType* storageId, Address* storageOffset, Address dataOffset) const;
    [[nodiscard]]
    Size size() const;

public: // introspection API, used for tests
    using ConstIterator = QLinkedList<Piece>::ConstIterator;

    // TODO: size() is more std-ish for number of elements, but used for address range so far here?
    [[nodiscard]]
    int piecesSize() const;
    [[nodiscard]]
    ConstIterator begin() const;
    [[nodiscard]]
    ConstIterator end() const;

private:
    enum class RemoveMergeMode {
        NoMerge,
        Merge,
    };
    PieceList doRemove(const AddressRange& removeRange, RemoveMergeMode mergeMode);

private:
    QLinkedList<Piece> mList;
    Size mSize;
};

inline PieceTable::~PieceTable() = default;

inline Size PieceTable::size() const { return mSize; }

inline int PieceTable::piecesSize() const { return mList.size(); }

inline PieceTable::ConstIterator PieceTable::begin() const { return mList.begin(); }
inline PieceTable::ConstIterator PieceTable::end() const { return mList.end(); }

}

#endif
