package ru.yandex.wmtools.common.util.scheduler.journal;

import java.util.Date;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.JdbcTemplate;

import ru.yandex.common.scheduler.Journal;
import ru.yandex.common.scheduler.JournalReader;
import ru.yandex.common.scheduler.TaskEvent;
import ru.yandex.common.scheduler.model.TaskDescriptor;
import ru.yandex.common.util.ApplicationUtil;
import ru.yandex.common.util.Su;
import ru.yandex.common.util.collections.Cu;
import ru.yandex.common.util.db.RowMappers;

/**
 * @author avhaliullin
 */
public class MySQLJournalWithTaskId implements Journal {
    private static final int MAX_MESSAGE_SIZE = 2000;

    private JdbcTemplate jdbcTemplate;

    private final String hostName = ApplicationUtil.getHostName();

    private final JournalReader journalReader = new JournalReader() {
        @Override
        public TaskEvent getLastEvent(final TaskDescriptor task) {
            final String event = Cu.firstOrNull(jdbcTemplate.query(
                    "select j.event from sch_journal j " +
                            "join ( " +
                            "  select max(j.record_id) r from sch_journal j " +
                            "  where j.task_id = ? " +
                            ") lj " +
                            "on lj.r = j.record_id and j.task_id = ?",
                    RowMappers.stringAt(1), task.getTaskId(), task.getTaskId()));
            return event == null ? null : TaskEvent.valueOf(event);
        }
    };

    @Override
    public JournalReader getJournalReader() {
        return journalReader;
    }

    @Override
    public long taskStarted(final long userId, final TaskDescriptor task) {
        record(new Date(), task.getTaskId(), task.getTaskName(), task.getTaskParams(), hostName, TaskEvent.STARTED, "");
        return -1;
    }

    private void record(final Date date, final long taskId, final String name, final String params, final String host, final TaskEvent event, final String message) {
        jdbcTemplate.update(
                "insert into sch_journal (time, task_id, task_name, task_params, host, event, message) " +
                        "values (?, ?, ?, ?, ?, ?, ?)",
                date, taskId, name, params, host, event.name(), Su.limit(message, MAX_MESSAGE_SIZE)
        );
    }

    @Override
    public void taskFailed(final long runId, final TaskDescriptor task, final String message) {
        record(new Date(), task.getTaskId(), task.getTaskName(), task.getTaskParams(), hostName, TaskEvent.FAILED, message);
    }

    @Override
    public void taskFinished(final long run_id, final TaskDescriptor task, final String message) {
        record(new Date(), task.getTaskId(), task.getTaskName(), task.getTaskParams(), hostName, TaskEvent.FINISHED, message);
    }

    @Override
    public void taskEvent(final long runId, final TaskDescriptor task, final String message) {
        record(new Date(), task.getTaskId(), task.getTaskName(), task.getTaskParams(), hostName, TaskEvent.EVENT, message);
    }

    @Required
    public void setJdbcTemplate(final JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}
