/*
 *
 *    Copyright (c) 2024 Project CHIP Authors
 *    All rights reserved.
 *
 *    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 <algorithm>
#include <array>
#include <stdio.h>

#include <pw_unit_test/framework.h>

#include <lib/core/StringBuilderAdapters.h>
#include <lib/support/SortUtils.h>
#include <lib/support/Span.h>

using namespace chip;
using namespace chip::Sorting;

namespace {

struct Datum
{
    // Key is the element that takes part in sorting.
    int key;
    // The associated data is constructed to detect stable sort.
    int associated_data;

    bool operator==(const Datum & other) const
    {
        return (this == &other) || ((this->key == other.key) && (this->associated_data == other.associated_data));
    }
};

class Sorter
{
public:
    virtual ~Sorter() = default;

    void Reset() { m_compare_count = 0; }

    size_t compare_count() const { return m_compare_count; }

    virtual void Sort(chip::Span<Datum> data) = 0;

protected:
    size_t m_compare_count = 0;
};

class InsertionSorter : public Sorter
{
public:
    void Sort(chip::Span<Datum> data)
    {
        InsertionSort(data.data(), data.size(), [&](const Datum & a, const Datum & b) -> bool {
            ++m_compare_count;
            return a.key < b.key;
        });
    }
};

void DoBasicSortTest(Sorter & sorter)
{
    Span<Datum> empty_to_sort;
    Span<Datum> empty_expected;

    std::array<Datum, 1> single_entry_to_sort{ { { 1, 100 } } };
    std::array<Datum, 1> single_entry_expected{ { { 1, 100 } } };

    std::array<Datum, 2> two_entries_to_sort{ { { 2, 200 }, { 1, 100 } } };
    std::array<Datum, 2> two_entries_expected{ { { 1, 100 }, { 2, 200 } } };

    std::array<Datum, 20> random_order_to_sort{ { { 1, 100 }, { 10, 1000 }, { 2, 200 },   { 13, 1300 }, { 4, 400 },
                                                  { 8, 800 }, { 10, 1001 }, { 6, 600 },   { 7, 700 },   { 7, 701 },
                                                  { 6, 601 }, { 6, 602 },   { 6, 603 },   { 8, 801 },   { 14, 1400 },
                                                  { 6, 604 }, { 10, 1002 }, { 12, 1200 }, { 4, 401 },   { 2, 201 } } };

    std::array<Datum, 20> random_order_expected{ { { 1, 100 },   { 2, 200 },   { 2, 201 },   { 4, 400 },   { 4, 401 },
                                                   { 6, 600 },   { 6, 601 },   { 6, 602 },   { 6, 603 },   { 6, 604 },
                                                   { 7, 700 },   { 7, 701 },   { 8, 800 },   { 8, 801 },   { 10, 1000 },
                                                   { 10, 1001 }, { 10, 1002 }, { 12, 1200 }, { 13, 1300 }, { 14, 1400 } } };

    std::array<Datum, 20> reverse_order_to_sort{ { { 20, 2000 }, { 19, 1900 }, { 18, 1800 }, { 17, 1700 }, { 16, 1600 },
                                                   { 15, 1500 }, { 14, 1400 }, { 13, 1300 }, { 12, 1200 }, { 11, 1100 },
                                                   { 10, 1000 }, { 9, 900 },   { 8, 800 },   { 7, 700 },   { 6, 600 },
                                                   { 5, 500 },   { 4, 400 },   { 3, 300 },   { 2, 200 },   { 1, 100 } } };

    std::array<Datum, 20> reverse_order_expected{ { { 1, 100 },   { 2, 200 },   { 3, 300 },   { 4, 400 },   { 5, 500 },
                                                    { 6, 600 },   { 7, 700 },   { 8, 800 },   { 9, 900 },   { 10, 1000 },
                                                    { 11, 1100 }, { 12, 1200 }, { 13, 1300 }, { 14, 1400 }, { 15, 1500 },
                                                    { 16, 1600 }, { 17, 1700 }, { 18, 1800 }, { 19, 1900 }, { 20, 2000 } } };

    std::array<Span<Datum>, 5> inputs = { { empty_to_sort, Span<Datum>(single_entry_to_sort), Span<Datum>(two_entries_to_sort),
                                            Span<Datum>(random_order_to_sort), Span<Datum>(reverse_order_to_sort) } };
    std::array<Span<Datum>, 5> expected_outs = { { empty_expected, Span<Datum>(single_entry_expected),
                                                   Span<Datum>(two_entries_expected), Span<Datum>(random_order_expected),
                                                   Span<Datum>(reverse_order_expected) } };

    for (size_t case_idx = 0; case_idx < inputs.size(); ++case_idx)
    {
        printf("Case index: %d\n", static_cast<int>(case_idx));
        auto & to_sort        = inputs[case_idx];
        const auto & expected = expected_outs[case_idx];

        sorter.Sort(to_sort);
        EXPECT_TRUE(to_sort.data_equal(expected));
        if (!to_sort.data_equal(expected))
        {
            for (size_t idx = 0; idx < to_sort.size(); ++idx)
            {
                Datum sorted_item   = to_sort[idx];
                Datum expected_item = expected[idx];
                printf("Index: %d, got { %d, %d }, expected { %d, %d }\n", static_cast<int>(idx), sorted_item.key,
                       sorted_item.associated_data, expected_item.key, expected_item.associated_data);
            }
        }
        EXPECT_LE(sorter.compare_count(), (to_sort.size() * to_sort.size()));
        printf("Compare counts: %d\n", static_cast<int>(sorter.compare_count()));
        sorter.Reset();
    }
}

TEST(TestSorting, TestBasicSort)
{
    printf("Testing insertion sorter.\n");
    InsertionSorter insertion_sorter;
    DoBasicSortTest(insertion_sorter);
}

} // namespace
