package ru.yandex.wmconsole.servantlet;

import java.net.IDN;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Required;

import ru.yandex.common.framework.core.ServRequest;
import ru.yandex.common.framework.core.ServResponse;
import ru.yandex.wmconsole.data.info.ShortHostInfo;
import ru.yandex.wmconsole.data.wrappers.ShortHostInfoWrapper;
import ru.yandex.wmconsole.service.ConsistentMainMirrorService;
import ru.yandex.wmconsole.service.UsersHostsService;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.servantlet.AbstractServantlet;
import ru.yandex.wmtools.common.util.XmlConvertableCollectionWrapper;

/**
 * Check verification status for given user and list of hosts. CHEAT verifications are excluded.
 * host names must be in ascii (punycode for IDN) and in lower case
 * @author senin
 */
public class CheckHostsVerifiedByUserServantlet extends AbstractServantlet {

    private static final String PARAM_UID = "uid";
    private static final String PARAM_HOST = "host";
    private static final String TAG_HOSTLIST = "hostlist";

    private UsersHostsService usersHostsService;
    private ConsistentMainMirrorService consistentMainMirrorService;


    @Override
    protected void doProcess(ServRequest req, final ServResponse res) throws UserException, InternalException {

        Long userId = getRequiredLongParam(req, PARAM_UID);
        List<String> hosts = req.getMultiParams(PARAM_HOST);

        if (!hosts.isEmpty()) {
            List<String> mainMirrors = new ArrayList<>(hosts.size());

            Map<String, String> main2original = new HashMap<String, String>();
            for (String hostName : hosts) {
                String mainMirror = consistentMainMirrorService.getMainMirror(hostName);
                mainMirrors.add(mainMirror);
                main2original.put(mainMirror, hostName);
            }

            List<ShortHostInfo> hostsVerifiedByUser = usersHostsService.checkHostsVerifiedByUser(userId, mainMirrors.toArray(new String[mainMirrors.size()]));

            List<CheckVerificationHostInfo> checkInfos = new ArrayList<CheckVerificationHostInfo>();
            for (ShortHostInfo info : hostsVerifiedByUser) {
                checkInfos.add(new CheckVerificationHostInfo(info, main2original.get(info.getPunycodeName())));
            }

            res.addData(XmlConvertableCollectionWrapper.wrap(checkInfos, CheckVerificationHostInfoWrapper.class, TAG_HOSTLIST));
        }
    }

    public static class CheckVerificationHostInfo extends ShortHostInfo {
        public String getOriginalHost() {
            return originalHost;
        }

        private String originalHost;

        public CheckVerificationHostInfo(ShortHostInfo info, String originalHost) {
            super(info.getId(), info.getName(), info.getVerificationState(), info.getVerificationType());
            this.originalHost = originalHost;
        }
    }

    public static class CheckVerificationHostInfoWrapper<T extends CheckVerificationHostInfo> extends ShortHostInfoWrapper<CheckVerificationHostInfo> {
        private static final String TAG_ORIGINAL_NAME = "original-name";
        private static final String TAG_ORIGINAL_PUNYCODE_NAME = "original-punycode-name";
        public CheckVerificationHostInfoWrapper(CheckVerificationHostInfo info) {
            super(info);
        }

        @Override
        protected void doToXml(StringBuilder result) {
            putHostnameTag(result, TAG_ORIGINAL_NAME, data.getOriginalHost());
            putTag(result, TAG_ORIGINAL_PUNYCODE_NAME, IDN.toASCII(data.getOriginalHost()));
            super.doToXml(result);
        }
    }

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

    @Required
    public void setConsistentMainMirrorService(ConsistentMainMirrorService consistentMainMirrorService) {
        this.consistentMainMirrorService = consistentMainMirrorService;
    }
}
