package ru.yandex.webmaster3.viewer.http.searchquery.statistic;

import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.searchquery.PathId;
import ru.yandex.webmaster3.core.searchquery.QueryIndicator;
import ru.yandex.webmaster3.core.searchquery.viewer.ViewerPath;
import ru.yandex.webmaster3.storage.http.searchquery.statistic.StatisticsHelper;
import ru.yandex.webmaster3.storage.searchquery.*;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;

import java.util.*;
import java.util.function.Function;

/**
 * @author lester
 */
@ReadAction
@Category("searchquery")
public class GetUrlPieChartAction extends AbstractUserVerifiedHostAction<GetUrlPieChartRequest, UrlStatisticsResponse> {
    @Autowired
    private UrlStatisticsService2 urlStatisticsService2;

    @Override
    public UrlStatisticsResponse process(GetUrlPieChartRequest request) throws WebmasterException {
        final LocalDate userRangeStart = request.getLocalDateFrom();
        final LocalDate userRangeEnd = request.getLocalDateTo();
        final List<PathId> pathIds = StatisticsHelper.asPathIds(7, request.getPathId());
        final Set<Integer> regions = StatisticsHelper.asSet(10, request.getRegionId());
        final QueryIndicator indicator = request.getIndicator();
        final List<QueryIndicator> indicators = Collections.singletonList(indicator);
        if (pathIds.isEmpty()) {
            throw new WebmasterException("Error",
                    new WebmasterErrorResponse.IllegalParameterValueResponse(this.getClass(), "queryId", null));
        }

        RangeSet<LocalDate> rangeSet = RangeFactory.singleRange(userRangeStart, userRangeEnd);
        Map<PathId, String> pathTexts =
                urlStatisticsService2.getPathTexts(request.getHostId(), request.getSpecialGroup(), pathIds);
        List<PathStat> statistics = urlStatisticsService2
                .getStatistics(request.getSpecialGroup(),
                        request.getHostId(),
                        indicators, pathIds,
                        regions, request.getRegionInclusion(),
                        rangeSet.span().lowerEndpoint(), rangeSet.span().upperEndpoint(), request.getDeviceType());

        List<UrlStatisticsResponse.PathStat> result = new ArrayList<>();

        Map<PathId, AccumulatorMap> accumulators = new HashMap<>();
        Function<PathId, AccumulatorMap> accumulatorFactory =
                q -> {
                    return AccumulatorMap.create(indicators, rangeSet);
                };
        for (PathStat pathStat : statistics) {
            AccumulatorMap ac = accumulators.computeIfAbsent(pathStat.getPathId(), accumulatorFactory);
            ac.apply(pathStat);
        }

        for (PathId pathId : pathIds) {
            String pathText = pathTexts.get(pathId);

            AccumulatorMap accumulatorMap = accumulators.computeIfAbsent(pathId, accumulatorFactory);

            List<Pair<Range<LocalDate>, Double>> indicatorStat = accumulatorMap.getIndicator(indicator);
            Pair<Range<LocalDate>, Double> rangeStat = indicatorStat.get(0);

            result.add(new UrlStatisticsResponse.PathStat(new ViewerPath(pathId, pathText),
                    new AbstractQueryStatisticsResponse.IndicatorStats(indicator, Collections.singletonList(
                            new AbstractQueryStatisticsResponse.RangeStat(
                                    rangeStat.getKey().lowerEndpoint(),
                                    rangeStat.getKey().upperEndpoint(),
                                    rangeStat.getValue(),
                                    null)
                    ))));
        }

        return new UrlStatisticsResponse.NormalResponse(null, null, result);
    }
}
