#include "scroll_window.h"

#include <algorithm>
#include <tuple>

namespace maps {
namespace wiki {
namespace socialsrv {

namespace {

std::pair<size_t, size_t> alignLeft(size_t size, size_t total, size_t anchor)
{ return {anchor, std::min(size, total - anchor)}; }

std::pair<size_t, size_t> alignRight(size_t size, size_t anchor)
{
    auto offset = 0;
    if (anchor + 1 >= size) {
        offset = anchor + 1 - size;
    }
    return {offset, std::min(size, anchor + 1)};
}

} // namespace

ScrollWindow::ScrollWindow()
    : offset_(0)
    , count_(0)
    , total_(0)
{ }

ScrollWindow::ScrollWindow(size_t size, size_t total, size_t anchor, Align align)
    : ScrollWindow()
{
    total_ = total;

    if (anchor >= total) {
        offset_ = total;
        return;
    }
    size = std::min(size, total);
    if (!size) {
        offset_ = anchor;
        return;
    }

    size_t rightMargin = 0;
    switch (align) {
        case Align::Center:
            count_ = size;

            std::tie(std::ignore, rightMargin) =
                alignLeft(size / 2 + 1, total, anchor);
            std::tie(offset_, std::ignore) =
                alignRight(size, anchor + rightMargin - 1);
            break;
        case Align::Left:
            std::tie(offset_, count_) = alignLeft(size, total, anchor);
            break;
        case Align::Right:
            std::tie(offset_, count_) = alignRight(size, anchor);
            break;
    }
}

size_t ScrollWindow::offset() const
{ return offset_; }

size_t ScrollWindow::count() const
{ return count_; }

bool ScrollWindow::hasBefore() const
{ return offset_ > 0; }

bool ScrollWindow::hasAfter() const
{ return total_ > 0 && offset_ + count_ < total_; }

} // namespace socialsrv
} // namespace wiki
} // namespace maps
