package ru.yandex.wmconsole.common.service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;

import ru.yandex.common.framework.pager.Pager;
import ru.yandex.webmaster.common.history.dao.TblHistoryDao;
import ru.yandex.wmconsole.data.WMCHistoryActionEnum;
import ru.yandex.wmconsole.data.WMCHistoryObjectTypeEnum;
import ru.yandex.wmconsole.data.partition.WMCPartition;
import ru.yandex.wmtools.common.data.HistoryActionEnum;
import ru.yandex.wmtools.common.data.HistoryObjectTypeEnum;
import ru.yandex.wmtools.common.data.IHistoryAction;
import ru.yandex.wmtools.common.data.IHistoryObjectType;
import ru.yandex.wmtools.common.data.info.HistoryInfo;
import ru.yandex.wmtools.common.data.info.WMUserInfo;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.service.HistoryService;
import ru.yandex.wmtools.common.util.SqlUtil;

/**
 * User: baton
 * Date: 29.06.2007
 * Time: 16:42:21
 */
public class WMCHistoryService extends HistoryService {
    private static final String FIELD_ID = "id";
    private static final String FIELD_USER_ID = "user_id";
    private static final String FIELD_VIRTUAL_USER_ID = "virtual_user_id";
    private static final String FIELD_ACTION = "action";
    private static final String FIELD_OBJECT_ID = "object_id";
    private static final String FIELD_PERFORMED_ON = "performed_on";
    private static final String FIELD_TYPE = "type";

    private static final String SELECT_HISTORY_LIST_QUERY =
            "SELECT " +
                    "    id AS " + FIELD_ID + ", " +
                    "    user_id AS " + FIELD_USER_ID + ", " +
                    "    virtual_user_id AS " + FIELD_VIRTUAL_USER_ID + ", " +
                    "    action AS " + FIELD_ACTION + ", " +
                    "    object_id AS " + FIELD_OBJECT_ID + ", " +
                    "    performed_on AS " + FIELD_PERFORMED_ON + ", " +
                    "    type AS " + FIELD_TYPE + " " +
                    "FROM " +
                    "    tbl_history " +
                    "WHERE " +
                    "    type IN (%1$s) " +
                    "AND " +
                    "    object_id = ? " +
                    "ORDER BY " +
                    "    performed_on DESC " +
                    " %2$s ";

    private static final String SELECT_HISTORY_LIST_COUNT_QUERY =
            "SELECT " +
                    "    count(*) " +
                    "FROM " +
                    "    tbl_history " +
                    "WHERE " +
                    "    type IN (%1$s) " +
                    "AND " +
                    "    object_id = ? ";

    private TblHistoryDao tblHistoryDao;

    private final ParameterizedRowMapper<HistoryInfo> HISTORY_INFO_ROW_MAPPER = new ParameterizedRowMapper<HistoryInfo>() {
        @Override
        public HistoryInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
            long id = rs.getLong(FIELD_ID);
            WMUserInfo user = null;
            try {
                user = getUserInfoService().getUserInfo(rs.getLong(FIELD_USER_ID));
            } catch (UserException e) {
                // skip error
            } catch (InternalException e) {
                // skip error
            }
            WMUserInfo virtualUser = null;
            try {
                virtualUser = getUserInfoService().getUserInfo(rs.getLong(FIELD_VIRTUAL_USER_ID));
            } catch (UserException e) {
                // skip error
            } catch (InternalException e) {
                // skip error
            }
            long objectId = rs.getLong(FIELD_OBJECT_ID);
            Date performedOn = SqlUtil.safeGetTimestamp(rs, FIELD_PERFORMED_ON);

            Byte actionValue = rs.getByte(FIELD_ACTION);
            IHistoryAction action = HistoryActionEnum.getByValue(actionValue);
            if (action == null) {
                action = WMCHistoryActionEnum.getByValue(actionValue);
            }

            Byte typeValue = rs.getByte(FIELD_TYPE);
            IHistoryObjectType type = HistoryObjectTypeEnum.getByValue(typeValue);
            if (type == null) {
                type = WMCHistoryObjectTypeEnum.R.fromValueOrNull(typeValue);
            }

            return new HistoryInfo(id, user, virtualUser, action, objectId, performedOn, type);
        }
    };

    @Override
    protected void addHistoryQuery(Long realUserId, Long virtualUserId, IHistoryAction historyAction,
            IHistoryObjectType historyObjectType, Long objectId, String newValue) throws InternalException {
        tblHistoryDao.addHistoryQuery(realUserId, virtualUserId, historyAction, historyObjectType, objectId, newValue);
    }

    @Override
    protected List<HistoryInfo> getHistoryListQuery(String countSql, String selectSql, long objectId, Pager pager, Object[] params) throws InternalException {
        return getJdbcTemplate(WMCPartition.nullPartition()).pageableSelect(countSql,
                selectSql, HISTORY_INFO_ROW_MAPPER, pager, params);
    }

    @Override
    protected String getHistoryListSelectWithPlaceholders() {
        return SELECT_HISTORY_LIST_QUERY;
    }

    @Override
    protected String getHistoryListCountWithPlaceholders() {
        return SELECT_HISTORY_LIST_COUNT_QUERY;
    }

    @Required
    public void setTblHistoryDao(TblHistoryDao tblHistoryDao) {
        this.tblHistoryDao = tblHistoryDao;
    }
}
