package ru.yandex.wmconsole.servantlet.hostname;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import ru.yandex.common.framework.core.ServRequest;
import ru.yandex.common.framework.core.ServResponse;
import ru.yandex.webmaster.viewer.service.NewWebmasterProxyService;
import ru.yandex.wmconsole.data.info.BriefHostInfo;
import ru.yandex.wmconsole.servantlet.WMCAuthorizedHostOperationServantlet;
import ru.yandex.wmconsole.service.CheckHostNameService;
import ru.yandex.wmconsole.service.error.WMCUserProblem;
import ru.yandex.wmtools.common.SupportedProtocols;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * Checks if specified display name is correct and changes it.
 *
 * @author ailyin
 */
public class ChangeHostnameServantlet extends WMCAuthorizedHostOperationServantlet {
    private static final Logger log = LoggerFactory.getLogger(ChangeHostnameServantlet.class);

    private static final String PARAM_DISPLAY_NAME = "displayname";

    private CheckHostNameService checkHostnameService;
    private NewWebmasterProxyService newWebmasterProxyService;

    @Override
    protected void doProcess(ServRequest req, ServResponse res, long userId) throws InternalException, UserException {
        log.debug("ChangeHostname: Started");

        BriefHostInfo briefHostInfo = getHostInfoAndVerify(req, userId);
        if (isIDN(briefHostInfo.getName())) {
            throw new UserException(WMCUserProblem.IDN_ARE_NOT_SUPPORTED,
                    "Can't change display name of a host with IDN: " + briefHostInfo.getName());
        }
        URL briefHostname;
        try {
            briefHostname = SupportedProtocols.getURL(briefHostInfo.getName());
        } catch (MalformedURLException e) {
            throw new AssertionError("invalid hostname in a database!");
        } catch (URISyntaxException e) {
            throw new AssertionError("invalid hostname in a database!");
        } catch (SupportedProtocols.UnsupportedProtocolException e) {
            throw new AssertionError("there is a host in a database with unsupported protocol!");
        }

        String displayName = getRequiredStringParam(req, PARAM_DISPLAY_NAME);
        if (displayName.contains(SCHEME_DELIMITER)) {
            // check protocols are equal
            String protocolPrefix = displayName.substring(0,
                    displayName.indexOf(SCHEME_DELIMITER) + SCHEME_DELIMITER.length()).toLowerCase();
            if (!briefHostInfo.getName().startsWith(protocolPrefix)) {
                throw new UserException(WMCUserProblem.NOT_MATCHING_DISPLAY_NAME,
                        "Specified hostname " + displayName + " has wrong protocol");
            }

            // add or remove "www." prefix
            String displayHost = displayName.substring(protocolPrefix.length());
            displayName = protocolPrefix + bringToStandardWwwPrefix(displayHost, briefHostname.getHost());
        } else {
            // add or remove "www." prefix
            displayName = bringToStandardWwwPrefix(displayName, briefHostname.getHost());

            // add protocol if necessary
            if (briefHostInfo.getName().startsWith(briefHostname.getProtocol() + SCHEME_DELIMITER)) {
                // protocol is NOT ommited (i.e. not a HTTP)
                displayName = briefHostname.getProtocol() + SCHEME_DELIMITER + displayName;
            }
        }

        checkHostnameService.checkDisplayName(briefHostInfo, displayName);

        newWebmasterProxyService.changeHostNameInfo(userId, briefHostInfo, displayName);
        log.debug("ChangeHostname: Finished");
    }

    @Required
    public void setCheckHostNameService(CheckHostNameService checkHostnameService) {
        this.checkHostnameService = checkHostnameService;
    }

    @Required
    public void setNewWebmasterProxyService(NewWebmasterProxyService newWebmasterProxyService) {
        this.newWebmasterProxyService = newWebmasterProxyService;
    }
}
