package ru.yandex.wmconsole.servantlet;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.core.io.InputStreamSource;

import ru.yandex.common.framework.core.RemoteFile;
import ru.yandex.common.framework.core.ServRequest;
import ru.yandex.common.framework.core.ServResponse;
import ru.yandex.webmaster.viewer.complaints.Complaint;
import ru.yandex.webmaster.viewer.complaints.ComplaintRecipient;
import ru.yandex.webmaster.viewer.complaints.ComplaintType;
import ru.yandex.webmaster.viewer.complaints.ComplaintsService;
import ru.yandex.webmaster.viewer.complaints.PhishingComplaintsService;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.error.UserProblem;
import ru.yandex.wmtools.common.servantlet.AbstractServantlet;

/**
 * @author avhaliullin
 */
public class ComplainAboutServantlet extends AbstractServantlet {
    private static final Logger log = LoggerFactory.getLogger(ComplainAboutServantlet.class);

    private static final String PARAM_TYPE = "type";
    private static final String PARAM_FROM_EMAIL = "from_email";
    private static final String PARAM_FROM_NAME = "from_name";
    private static final String PARAM_IP = "ip";

    private static final String PARAM_URL = "url";
    private static final String PARAM_MESSAGE = "message";
    private static final String PARAM_QUERY = "query";

    private static final String PARAM_DEV_EMAIL = "mail_dev";

    private static final long MAX_ATTACHMENT_LENGTH = 1024 * 1024;
    public static final String COOKIE_NAME = "ys";

    private PhishingComplaintsService phishingComplaintsService;
    private ComplaintsService complaintsService;


    @Override
    protected void doProcess(ServRequest req, ServResponse res) throws UserException, InternalException {
        ComplaintType complainType = getComplainType(getRequiredStringParam(req, PARAM_TYPE));

        String url = getRequiredStringParam(req, PARAM_URL);
        url = doPrepareUrl(url, true, false).toString();
        String message = getRequiredStringParam(req, PARAM_MESSAGE);
        if (complainType == ComplaintType.PHISHING) {
            // Жалоба на фишинг отправляется в спам-базу
            phishingComplaintsService.sendPhishingComplaint(url, message);
        } else {
            String fromEmail = getStringParam(req, PARAM_FROM_EMAIL);
            String fromName = getStringParam(req, PARAM_FROM_NAME);
            String address = getStringParam(req, PARAM_DEV_EMAIL);
            ComplaintRecipient recipient = new ComplaintRecipient(fromEmail, fromName, address);

            Complaint complaint = new Complaint(complainType, url, message);
            complaint.setIp(getStringParam(req, PARAM_IP));
            complaint.setCookies(req.getCookie(COOKIE_NAME));

            if (complainType == ComplaintType.SPAM) {
                complaint.setQuery(getRequiredStringParam(req, PARAM_QUERY));
            }

            String attachmentName = null;
            InputStreamSource attachmentISS = null;

            @SuppressWarnings({"unchecked"})
            List<RemoteFile> files = req.getRemoteFiles();
            if (files != null && !files.isEmpty() && files.get(0).getSize() > 0) {
                final RemoteFile file = files.get(0);
                log.debug("Attach file: \"" + file.getOriginalFilename() + "\", size: " + file.getSize());
                attachmentName = file.getOriginalFilename();
                attachmentISS = getBufferedFileContent(file, MAX_ATTACHMENT_LENGTH);
            }

            complaintsService.sendComplaint(complaint, recipient, attachmentName, attachmentISS);
        }
    }

    private static ComplaintType getComplainType(String typeStr) throws UserException {
        if ("spam".equals(typeStr)) {
            return ComplaintType.SPAM;
        } else if ("virus".equals(typeStr)) {
            return ComplaintType.VIRUS;
        } else if ("phishing".equals(typeStr)) {
            return ComplaintType.PHISHING;
        } else if ("unwanted-software".equals(typeStr)) {
            return ComplaintType.UNWANTED_SOFTWARE;
        }

        throw new UserException(UserProblem.ILLEGAL_PARAM_VALUE, "Unknown complaint type", PARAM_TYPE, typeStr);
    }

    @Required
    public void setPhishingComplaintsService(PhishingComplaintsService phishingComplaintsService) {
        this.phishingComplaintsService = phishingComplaintsService;
    }

    @Required
    public void setComplaintsService(ComplaintsService complaintsService) {
        this.complaintsService = complaintsService;
    }
}
