#include <yandex/maps/mrc/toloka_client/assignment.h>
#include "assignment_impl.h"

#include <utility>

namespace maps {
namespace mrc {
namespace toloka {
namespace io {

namespace {

const std::vector<std::pair<AssignmentStatus, std::string>>
ASSIGNMENT_STATUS_NAMES{
    {AssignmentStatus::Active, "ACTIVE"},
    {AssignmentStatus::Submitted, "SUBMITTED"},
    {AssignmentStatus::Accepted, "ACCEPTED"},
    {AssignmentStatus::Rejected, "REJECTED"},
    {AssignmentStatus::Skipped, "SKIPPED"},
    {AssignmentStatus::Expired, "EXPIRED"}
};

} // anonymous namespace

std::ostream& operator<<(std::ostream& os, AssignmentStatus status)
{
    auto itr
        = std::find_if(ASSIGNMENT_STATUS_NAMES.begin(),
                       ASSIGNMENT_STATUS_NAMES.end(),
                       [&](const std::pair<AssignmentStatus, std::string>& pair) {
                           return pair.first == status;
                       });
    REQUIRE(itr != ASSIGNMENT_STATUS_NAMES.end(),
            "Bad assignment status value: " << static_cast<int>(status));
    return os << itr->second;
}

std::istream& operator>>(std::istream& is, AssignmentStatus& status)
{
    std::string str;
    is >> str;
    auto itr
        = std::find_if(ASSIGNMENT_STATUS_NAMES.begin(),
                       ASSIGNMENT_STATUS_NAMES.end(),
                       [&](const std::pair<AssignmentStatus, std::string>& pair) {
                           return pair.second == str;
                       });
    REQUIRE(itr != ASSIGNMENT_STATUS_NAMES.end(),
            "Bad assignment status: " << str);
    status = itr->first;
    return is;
}


COPYABLE_PIMPL_DEFINITIONS(AssignmentSolution)

const json::Value& AssignmentSolution::outputValues() const
{
    return impl_->outputValues_;
}


MOVABLE_PIMPL_DEFINITIONS(Assignment)

const std::string& Assignment::id() const { return impl_->id_; }

const std::string& Assignment::poolId() const { return impl_->poolId_; }

AssignmentStatus Assignment::status() const {return impl_->status_; }

const std::string& Assignment::taskSuiteId() const
{
    return impl_->taskSuiteId_;
}

const std::string& Assignment::userId() const { return impl_->userId_; }

chrono::TimePoint Assignment::createdAt() const
{
    return impl_->createdAt_;
}

const boost::optional<chrono::TimePoint>& Assignment::submittedAt() const
{
    return impl_->submittedAt_;
}

const boost::optional<chrono::TimePoint>& Assignment::acceptedAt() const
{
    return impl_->acceptedAt_;
}

const TaskSuiteItems& Assignment::tasks() const
{
    return impl_->tasks_;
}

const AssignmentSolutions& Assignment::solutions() const
{
    return impl_->solutions_;
}



MOVABLE_PIMPL_DEFINITIONS(AssignmentsResponse)

const Assignments& AssignmentsResponse::assignments() const
{
    return impl_->assignments_;
}

bool AssignmentsResponse::hasMore() const { return impl_->hasMore_; }


} // namespace io
} // namespace toloka
} // namespace mrc
} // namespace maps

