package ru.yandex.wmconsole.servantlet.trends;

import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
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.webmaster.common.urltree.YandexSearchShard;
import ru.yandex.wmconsole.data.IndexingEntityEnum;
import ru.yandex.wmconsole.data.info.BriefHostInfo;
import ru.yandex.wmconsole.data.info.HostDbHostInfo;
import ru.yandex.wmconsole.data.wrappers.highchart.JsonHighchartPlotDataWrapper;
import ru.yandex.wmconsole.servantlet.WMCAuthorizedHostOperationServantlet;
import ru.yandex.wmconsole.service.HostDbHostInfoService;
import ru.yandex.wmconsole.service.IndexHistoryService;
import ru.yandex.wmconsole.service.dao.TblUrlTreesDao;
import ru.yandex.wmtools.common.data.plot.DateLongPlotHelper;
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;

/**
 * Данные для графика истории индексирования показателя
 *
 * Параметры:
 * host - id хоста в пользовательской БД
 * type - тип показателя
 * node - id узла из структуры сайта
 *
 * User: azakharov
 * Date: 01.02.13
 * Time: 13:11
 */
public class IndexHistoryPlotDataServantlet extends WMCAuthorizedHostOperationServantlet {

    private static final String PARAM_TYPE = "type";
    private static final String PARAM_NODE = "node";

    private static final String PLOT_NAME = "Index History Graph";
    private static final String PARAM_JSON = "json";

    private IndexHistoryService indexHistoryService;
    private TblUrlTreesDao tblUrlTreesDao;
    private HostDbHostInfoService hostDbHostInfoService;

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

        BriefHostInfo hostInfo = getHostInfoAndVerify(req, userId);
        IndexingEntityEnum entity = getHistoryEntityType(req);
        Long node = getNodeParam(req, entity);
        YandexSearchShard searchShard = YandexSearchShard.RU;
        if (entity.isEntityForSearchShard()) {
            HostDbHostInfo hostDbHostInfo = hostDbHostInfoService.getHostDbHostInfo(hostInfo.getName());
            searchShard = tblUrlTreesDao.getOptimumShardId(hostDbHostInfo);
        }
        NavigableMap<Date, Long> data = indexHistoryService.getIndexHistoryPlotData(hostInfo, entity, node, searchShard);
        DatePlotHelper<Long> longPlotHelper = new DateLongPlotHelper(PlotHelper.InterpolateMode.NULL);
        longPlotHelper.setDateFormat(new UnixTimestampDateFormat(true));

        boolean json = getBooleanParam(req, PARAM_JSON, true);
        if (json) {
            res.addData(
                    new JsonHighchartPlotDataWrapper<Date, Long>(
                            PLOT_NAME,
                            Collections.singletonList(data),
                            Collections.singletonList(entityNames.get(entity)),
                            longPlotHelper));
        } else {
            res.addData(
                    new HighchartPlotDataWrapper<Date, Long>(
                            PLOT_NAME,
                            Collections.singletonList(data),
                            Collections.singletonList(entityNames.get(entity)),
                            longPlotHelper));
        }
    }

    private IndexingEntityEnum getHistoryEntityType(final ServRequest req) throws UserException {
        String type = getRequiredStringParam(req, PARAM_TYPE);
        IndexingEntityEnum entity = typeValues.get(type);
        if (entity == null) {
            throw new UserException(UserProblem.ILLEGAL_VALUE_TYPE, "Invalid param: " + PARAM_TYPE, PARAM_TYPE, type);
        }
        return entity;
    }

    private Long getNodeParam(final ServRequest request, final IndexingEntityEnum entity) throws UserException {
        if (entity.isEntityForNode()) {
            return getRequiredLongParam(request, PARAM_NODE);
        } else {
            return null;
        }
    }

    // отображение имени параметра во внутрений enum
    private static final Map<String, IndexingEntityEnum> typeValues =
            new LinkedHashMap<String, IndexingEntityEnum>();
    // отображение внутреннего enum в имя
    private static final Map<IndexingEntityEnum, String> entityNames =
            new LinkedHashMap<IndexingEntityEnum, String>();

    static {
        typeValues.put("urls", IndexingEntityEnum.ROBOTDB_INFO_URLS);
        typeValues.put("index_count", IndexingEntityEnum.ROBOTDB_INFO_INDEX_COUNT);
        typeValues.put("links_count", IndexingEntityEnum.LINKS_COUNT);
        typeValues.put("tcy", IndexingEntityEnum.TCY);
        typeValues.put("tree_urls", IndexingEntityEnum.URL_TREES_URLS);
        typeValues.put("tree_index_count", IndexingEntityEnum.URL_TREES_INDEX_COUNT);
        for (Map.Entry<String, IndexingEntityEnum> entry : typeValues.entrySet()) {
            entityNames.put(entry.getValue(), entry.getKey());
        }
    }

    @Required
    public void setIndexHistoryService(IndexHistoryService indexHistoryService) {
        this.indexHistoryService = indexHistoryService;
    }

    @Required
    public void setTblUrlTreesDao(TblUrlTreesDao tblUrlTreesDao) {
        this.tblUrlTreesDao = tblUrlTreesDao;
    }

    @Required
    public void setHostDbHostInfoService(HostDbHostInfoService hostDbHostInfoService) {
        this.hostDbHostInfoService = hostDbHostInfoService;
    }
}
