package ru.yandex.wmconsole.notifier.handler;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.yandex.wmconsole.data.HostInfoStatusEnum;
import ru.yandex.wmconsole.data.NotificationTypeEnum;
import ru.yandex.wmconsole.service.HostStatusChangedService;
import ru.yandex.wmconsole.service.NotificationService;
import ru.yandex.wmconsole.service.UsersHostsService;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;

/**
 * User: Alexey Zakharov <azakharov@yandex-team.ru>
 * Date: 30.12.11
 */
public class HostStatusChangedHandler implements Handler {
    private static final Logger log = LoggerFactory.getLogger(HostStatusChangedHandler.class);

    private static final String PARAM_HOST_ID = "host_id";
    private static final String PARAM_HOST_STATUS = "status";
    private static final String PARAM_SPIDER_IP = "spider_ip";
    private static final String PARAM_LAST_ACCESS = "last_access";

    private NotificationService notificationService;
    private UsersHostsService usersHostsService;
    private HostStatusChangedService hostStatusChangedService;

    public void setNotificationService(final NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void setUsersHostsService(final UsersHostsService usersHostsService) {
        this.usersHostsService = usersHostsService;
    }

    public void setHostStatusChangedService(final HostStatusChangedService hostStatusChangedService) {
        this.hostStatusChangedService = hostStatusChangedService;
    }

    @Override
    public void handleNotification(String xmlData) {
        throw new UnsupportedOperationException("Only internal notification supported. Use handleInternalNotification");
    }

    @Override
    public void internalHandle(String... params) {
        throw new UnsupportedOperationException("Method is deprecated and will be removed soon. Use handlerInternalNotification.");
    }

    @Override
    public void handleInternalNotification(final Map<String, String> params) {
        try {
            // Проверяем наличие обязательных параметров
            final Long hostId = MapParamUtil.getRequiredLongParam(params, PARAM_HOST_ID);
            final int status = MapParamUtil.getRequiredIntParam(params, PARAM_HOST_STATUS);
            log.debug("internalHandle for HOST_STATUS_CHANGED: host_id=" + hostId +
                    " status=" + status);
            // spider ip может отсутствовать
            String spiderIp = MapParamUtil.getStringParam(params, PARAM_SPIDER_IP);
            spiderIp = spiderIp == null ? "" : spiderIp;
            // last access может отсутствовать
            final Date lastAccess = MapParamUtil.getDateParam(params, PARAM_LAST_ACCESS);

            try {
                final long issueId = hostStatusChangedService.addHostStatusChanged(hostId, status, spiderIp, lastAccess);
                final List<Long> userIds = usersHostsService.getHostVerifiedUserIds(hostId);
                final HostInfoStatusEnum enumStatus = HostInfoStatusEnum.R.fromValueOrNull(status);
                if (enumStatus == null) {
                    log.warn("Status " + status + " is not valid. Skipping notification.");
                    return;
                }
                final NotificationTypeEnum notificationType;
                switch (enumStatus) {
                    case CONNECTION_FAILED: notificationType = null; break;
                    case DNS_ERROR:         notificationType = null; break;
                    case DISALLOW:          notificationType = null; break;
                    case DISALLOW_YANDEX:   notificationType = null; break;
                    case WILL_CONNECTION_FAILED: notificationType = NotificationTypeEnum.HOST_STATUS_WILL_CONNECTION_FAILED; break;
                    case WILL_DNS_ERROR:         notificationType = NotificationTypeEnum.HOST_STATUS_WILL_DNS_ERROR; break;
                    case WILL_DISALLOW:          notificationType = NotificationTypeEnum.HOST_STATUS_WILL_DISALLOW; break;
                    case WARN_CONNECTION_FAILED: notificationType = NotificationTypeEnum.HOST_STATUS_WARN_CONNECTION_FAILED; break;
                    case WARN_DNS_ERROR:         notificationType = null; break;
                    case WARN_DISALLOW:          notificationType = NotificationTypeEnum.HOST_STATUS_WARN_DISALLOW; break;
                    default: {
                        log.warn("Status " + status + " is not valid for HOST_STATUS_CHANGED notification type. Skipping notification.");
                        return;
                    }
                }
                if (notificationType == null) {
                    log.info("Notification skipped for host_id=" + hostId + " and status=" + enumStatus);
                    return;
                }
                notificationService.insertNotificationForUsers(notificationType, issueId, userIds, new Date());
            } catch (InternalException e) {
                log.error("InternalException in " + getClass().getName() + " " + "while inserting notification(s)", e);
            }
        } catch (UserException e) {
            String error = "Internal notify: Required param missed.";
            log.error(error, e);
        }
    }
}
