package ru.yandex.webmaster3.viewer.http.search;

import java.util.Comparator;
import java.util.List;
import java.util.NavigableMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.joda.time.Instant;
import org.springframework.beans.factory.annotation.Required;

import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.searchbase.SearchBaseDates;
import ru.yandex.webmaster3.core.searchbase.SearchBaseUpdateInfo;
import ru.yandex.webmaster3.storage.searchbase.SearchBaseUpdatesService;
import ru.yandex.webmaster3.viewer.http.BaseWebmaster3Action;

/**
 * @author aherman
 */
@ReadAction
@Category("search")
public class GetSearchBaseUpdatesAction extends BaseWebmaster3Action<GetSearchBaseUpdatesRequest, GetSearchBaseUpdatesResponse> {
    private SearchBaseUpdatesService searchBaseUpdatesService;

    @Override
    public GetSearchBaseUpdatesResponse process(GetSearchBaseUpdatesRequest request) {
        SearchBaseDates searchBaseUpdates = searchBaseUpdatesService.getSearchBaseUpdates();
        NavigableMap<Instant, SearchBaseUpdateInfo> switchDate2Info = searchBaseUpdates.getSwitchDate2Info();

        Predicate<SearchBaseUpdateInfo> predicate = bi -> true;
        if (request.getSwitchedFrom() != null) {
            predicate = predicate.and(
                    bi -> request.getSwitchedFrom().isBefore(bi.getBaseSwitchDate())
            );
        }
        if (request.getSwitchedTo() != null) {
            predicate = predicate.and(
                    bi -> request.getSwitchedTo().isAfter(bi.getBaseSwitchDate())
            );
        }
        if (request.getCollectedFrom() != null) {
            predicate = predicate.and(
                    bi -> request.getCollectedFrom().isBefore(bi.getBaseCollectionDate())
            );
        }
        if (request.getCollectedTo() != null) {
            predicate = predicate.and(
                    bi -> request.getCollectedTo().isAfter(bi.getBaseCollectionDate())
            );
        }

        List<GetSearchBaseUpdatesResponse.BaseInfo> result = switchDate2Info.values().stream()
                .filter(predicate)
                .sorted(Comparator.comparing(SearchBaseUpdateInfo::getBaseSwitchDate))
                .map(bi -> new GetSearchBaseUpdatesResponse.BaseInfo(
                        bi.getBaseCollectionDate(),
                        bi.getBaseSwitchDate()))
                .collect(Collectors.toList());

        return new GetSearchBaseUpdatesResponse.NormalResponse(result);
    }

    @Required
    public void setSearchBaseUpdatesService(SearchBaseUpdatesService searchBaseUpdatesService) {
        this.searchBaseUpdatesService = searchBaseUpdatesService;
    }
}
