package ru.yandex.wmconsole.notifier.handler;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import ru.yandex.common.util.collections.Cu;
import ru.yandex.common.util.functional.Fu;
import ru.yandex.webmaster.common.host.dao.TblHostsMainDao;
import ru.yandex.webmaster.common.host.dao.TblUsersHostsDao;
import ru.yandex.wmconsole.data.NotificationTypeEnum;
import ru.yandex.wmconsole.data.info.BriefHostInfo;
import ru.yandex.wmconsole.service.ClearBadSoftwareNotificationService;
import ru.yandex.wmconsole.service.NotificationService;
import ru.yandex.wmtools.common.SupportedProtocols;
import ru.yandex.wmtools.common.error.InternalException;

import java.io.IOException;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * User: azakharov
 * Date: 08.08.14
 * Time: 15:32
 */
public class ClearBadSoftwareNotificationHandler implements Handler {

    private static final Logger log = LoggerFactory.getLogger(ClearBadSoftwareNotificationHandler.class);

    private TblHostsMainDao tblHostsMainDao;
    private TblUsersHostsDao tblUsersHostsDao;
    private ClearBadSoftwareNotificationService clearBadSoftwareNotificationService;
    private NotificationService notificationService;

    @Override
    public void handleNotification(final String xmlData) {

        log.info("Clear bad software notification received externally");
        List<String> hosts = parseXmlData(xmlData);

        for (String host : hosts) {
            try {
                URL hostUrl = SupportedProtocols.getURL(host);
                String hostName = SupportedProtocols.getCanonicalHostname(hostUrl);

                BriefHostInfo hostInfo = tblHostsMainDao.getHostIdByHostname(hostName);
                if (hostInfo == null) {
                    continue;
                }

                List<Long> users = tblUsersHostsDao.getVerifiedUserByHosts(hostInfo.getId());
                if (users.isEmpty()) {
                    continue;
                }

                Date receiveTime = new Date();
                Long issueId = clearBadSoftwareNotificationService.saveNotificationInfo(hostInfo.getId(), receiveTime);

                notificationService.insertNotificationForUsers(
                        NotificationTypeEnum.CLEAR_BAD_SOFTWARE, issueId, users, receiveTime);
            } catch (MalformedURLException e) {
                log.error("Malformed url " + host, e);
                continue;
            } catch (URISyntaxException e) {
                log.error("URI syntax error " + host, e);
                continue;
            } catch (SupportedProtocols.UnsupportedProtocolException e) {
                log.error("Unsupported protocol " + host, e);
            } catch (InternalException e) {
                log.error("Internal exception for host: " + host, e);
            }

        }
    }

    private List<String> parseXmlData(String xmlData) {
        StringReader stringReader = new StringReader(xmlData);
        SAXBuilder builder = new SAXBuilder();
        try {
            Document document = builder.build(stringReader);
            Element rootElement = document.getRootElement();
            List<String> result = Cu.map(nameOf(), rootElement.getChildren("host"));
            log.debug("Cleared bad software hosts count: {}", result.size());
            return result;
        } catch (JDOMException e) {
            log.error("JDOM exception", e);
            return Collections.emptyList();
        } catch (IOException e) {
            log.error("IO exception", e);
            return Collections.emptyList();
        }
    }

    private Fu<Element, String> nameOf() {
        return new Fu<Element, String>(){
            @Override
            public String apply(Element element) {
                return element.getAttributeValue("name");
            }
        };
    }

    @Override
    public void internalHandle(String... params) {
        throw new UnsupportedOperationException("internalHandle is not supported");
    }

    @Override
    public void handleInternalNotification(Map<String, String> params) {
        throw new UnsupportedOperationException("handleInternalNotification is not supported");
    }

    @Required
    public void setTblHostsMainDao(TblHostsMainDao tblHostsMainDao) {
        this.tblHostsMainDao = tblHostsMainDao;
    }

    @Required
    public void setTblUsersHostsDao(TblUsersHostsDao tblUsersHostsDao) {
        this.tblUsersHostsDao = tblUsersHostsDao;
    }

    @Required
    public void setClearBadSoftwareNotificationService(ClearBadSoftwareNotificationService clearBadSoftwareNotificationService) {
        this.clearBadSoftwareNotificationService = clearBadSoftwareNotificationService;
    }

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