#include "sort.h"
#include <util/generic/algorithm.h>

namespace NPrivate {
    class TSort::TComparer {
    public:
        TComparer(const TFullSort& sort)
            : Sort(sort)
        {}

        inline bool operator()(const NJson::TJsonValue& first, const NJson::TJsonValue& second) const {
            for (const auto& sort : Sort) {
                int c = Cmp(sort, first, second);
                if (c != 0)
                    return c < 0;
            }
            return false;
        }

    private:
        inline int Cmp(const TSort& sort, const NJson::TJsonValue& first, const NJson::TJsonValue& second) const {
            TString fv = first.Has(sort.Field) ? first[sort.Field].GetStringRobust() : "";
            TString sv = second.Has(sort.Field) ? second[sort.Field].GetStringRobust() : "";
            if (sort.Numeric) {
                size_t len = Max<size_t>(fv.size(), sv.size());
                if (fv.size() < len)
                    fv = TString(len - fv.size(), '0') + fv;
                if (sv.size() < len)
                    sv = TString(len - sv.size(), '0') + sv;
            }
            return (sort.Back ? -1 : 1) * strcmp(fv.data(), sv.data());
        }
        const TVector<TSort>& Sort;
    };

    TSort::TSort(const TString& str) {
        Numeric = str.StartsWith('#');
        Field = str.substr(Numeric ? 1 : 0);
        Back = false;
    }

    void TSort::SortJson(NJson::TJsonValue& result, const TFullSort& sort) {
        NJson::TJsonValue::TArray resArray;
        if (!sort.empty() && result.GetArray(&resArray) && !resArray.empty()) {
            Sort(resArray.begin(), resArray.end(), TComparer(sort));
            for (size_t i = 0; i < resArray.size(); ++i) {
                result[i] = resArray[i];
            }
        }
    }
}
