package ru.yandex.wmconsole.servantlet.errors;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.NavigableMap;

import org.springframework.beans.factory.annotation.Required;

import ru.yandex.common.framework.core.ServRequest;
import ru.yandex.common.framework.core.ServResponse;
import ru.yandex.wmconsole.data.LastDaysFilterEnum;
import ru.yandex.wmconsole.data.info.BriefHostInfo;
import ru.yandex.wmconsole.servantlet.WMCAuthorizedHostOperationServantlet;
import ru.yandex.wmconsole.service.HostDailyStateService;
import ru.yandex.wmtools.common.data.plot.DateIntegerPlotHelper;
import ru.yandex.wmtools.common.data.plot.DatePlotHelper;
import ru.yandex.wmtools.common.data.plot.HighchartPlotDataWrapper;
import ru.yandex.wmtools.common.data.plot.PlotHelper;
import ru.yandex.wmtools.common.data.plot.UnixTimestampDateFormat;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.error.UserProblem;
import ru.yandex.wmtools.common.util.TimeFilter;

public class ErrorPlotDataServantlet extends WMCAuthorizedHostOperationServantlet {
    private static final String PARAM_NODE_ID = "node-id";
    private static final String PARAM_CODE = "code";
    private static final String PARAM_LAST = "last";

    private static final String ERROR_SUMMARY_PLOT_NAME = "error_summary";
    private static final String ERROR_SUMMARY_FOR_CODE_LABEL = "error_summary_for_code";

    private HostDailyStateService hostDailyStateService;

    private static final DatePlotHelper<Integer> integerPlotHelper = new DateIntegerPlotHelper(PlotHelper.InterpolateMode.NULL);

    static {
        integerPlotHelper.setDateFormat(new UnixTimestampDateFormat(true));
    }

    @Override
    public void doProcess(ServRequest req, ServResponse res, long userId) throws UserException, InternalException {

        long nodeId = getRequiredLongParam(req, PARAM_NODE_ID);
        int code = getRequiredIntParam(req, PARAM_CODE);
        TimeFilter timeFilter = createTimeFilter(req);

        BriefHostInfo hostInfo = getHostInfoAndVerify(req, userId);
        // Проверяем, что сайт проиндексирован обычным роботом или быстророботом
        checkIndexed(hostInfo);

        NavigableMap<Date, Integer> hostDailyStates = hostDailyStateService.getErrorHistoryForNodeAndCode(
                hostInfo, nodeId, code, timeFilter);

        List<String> labels = Collections.singletonList(ERROR_SUMMARY_FOR_CODE_LABEL);
        final List<NavigableMap<Date, Integer>> data =
                (hostDailyStates.size() > 1) ?
                        Collections.singletonList(hostDailyStates) :
                        Collections.<NavigableMap<Date, Integer>>emptyList();
        res.addData(new HighchartPlotDataWrapper<Date, Integer>(ERROR_SUMMARY_PLOT_NAME, data, labels, integerPlotHelper, true));
    }

    private TimeFilter createTimeFilter(ServRequest req) throws UserException {
        Integer lastDays = getIntParam(req, PARAM_LAST);

        Calendar now = Calendar.getInstance();
        TimeFilter timeFilter = null;
        boolean needFilter = false;
        if (LastDaysFilterEnum.ONE_WEEK.getIntegerValue().equals(lastDays)) {
            now.add(Calendar.WEEK_OF_YEAR, -1);
            needFilter = true;
        } else if (LastDaysFilterEnum.TWO_WEEKS.getIntegerValue().equals(lastDays)) {
            now.add(Calendar.WEEK_OF_YEAR, -2);
            needFilter = true;
        }

        if (needFilter) {
            Integer year = now.get(Calendar.YEAR);
            Integer month = now.get(Calendar.MONTH) + 1;
            Integer day = now.get(Calendar.DATE);
            String after = year.toString() + "/" + month.toString() + "/" + day.toString();

            try {
                timeFilter = TimeFilter.create(after, null, "yyyy/MM/dd");
            } catch (ParseException e) {
                throw new UserException(UserProblem.ILLEGAL_VALUE_TYPE, "failed to parse date", e);
            }
        }

        return timeFilter;
    }

    @Required
    public void setHostDailyStateService(HostDailyStateService hostDailyStateService) {
        this.hostDailyStateService = hostDailyStateService;
    }
}
