package ru.yandex.wmconsole.servantlet;

import java.nio.charset.Charset;

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.service.UsersHostsService;
import ru.yandex.wmconsole.util.SimpleUsersHostsInfoHandler;
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.service.OwnerDomainService;

/**
 * Выдает подтвержденные хосты для справочника.
 *
 * @author avhaliullin
 */
public class AllVerifiedUsersHostsServantlet extends AbstractServantlet {
    private static final Charset CHARSET = Charset.forName("utf8");
    private static final byte[] HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".getBytes(CHARSET);
    private static final byte[] TAG_LIST_NAME = "users-hosts-list".getBytes(CHARSET);
    private static final byte[] TAG_INFO = "info".getBytes(CHARSET);
    private static final byte[] TAG_USER_ID = "user-id".getBytes(CHARSET);
    private static final byte[] TAG_HOST_NAME = "host-name".getBytes(CHARSET);
    private static final String PARAM_REMAINDER = "remainder";
    private static final String PARAM_MODULE = "module";
    private static final String PARAM_OWNER = "owner";

    private UsersHostsService usersHostsService;

    private static final byte[] START_TAG = "<".getBytes(CHARSET);
    private static final byte[] END_TAG = ">".getBytes(CHARSET);
    private static final byte[] START_ENDING_TAG = "</".getBytes(CHARSET);
    private static final byte[] SPACE = " ".getBytes(CHARSET);
    private static final byte[] START_ATTRIBUTE = "=\"".getBytes(CHARSET);
    private static final byte[] END_ATTRIBUTE = "\"".getBytes(CHARSET);

    private void startTag(ServResponse res, byte[] name, byte[]... attrs) {
        res.write(START_TAG);
        res.write(name);
        if (attrs.length % 2 == 0) {
            for (int i = 0; i < attrs.length; i += 2) {
                res.write(SPACE);
                res.write(attrs[i]);
                res.write(START_ATTRIBUTE);
                res.write(attrs[i + 1]);
                res.write(END_ATTRIBUTE);
            }
        }
        res.write(END_TAG);
    }

    private void endTag(ServResponse res, byte[] name) {
        res.write(START_ENDING_TAG);
        res.write(name);
        res.write(END_TAG);
    }

    @Override
    protected void doProcess(ServRequest req, final ServResponse res) throws UserException, InternalException {
        Long remainder = getRequiredLongParam(req, PARAM_REMAINDER);
        Long module = getRequiredLongParam(req, PARAM_MODULE);
        Boolean owner = getBooleanParam(req, PARAM_OWNER, false);
        SimpleUsersHostsInfoHandler handler = new SimpleUsersHostsInfoHandler() {
            @Override
            public void handleInfo(String hostName, long userId) {
                startTag(res, TAG_INFO);

                startTag(res, TAG_HOST_NAME);
                res.write(hostName.getBytes(CHARSET));
                endTag(res, TAG_HOST_NAME);

                startTag(res, TAG_USER_ID);
                res.write(String.valueOf(userId).getBytes(CHARSET));
                endTag(res, TAG_USER_ID);

                endTag(res, TAG_INFO);
            }
        };
        SimpleUsersHostsInfoHandler ownerHandler = new SimpleUsersHostsInfoHandler() {
            @Override
            public void handleInfo(String hostName, long userId) {
                startTag(res, TAG_INFO);

                String owner = hostName;
                try {
                    owner = OwnerDomainService.getOwnerHost(hostName.toLowerCase());
                } catch (InternalException e) {
                    //ignore exception
                }
                startTag(res, TAG_HOST_NAME);
                res.write(owner.getBytes(CHARSET));
                endTag(res, TAG_HOST_NAME);

                startTag(res, TAG_USER_ID);
                res.write(String.valueOf(userId).getBytes(CHARSET));
                endTag(res, TAG_USER_ID);

                endTag(res, TAG_INFO);
            }
        };
        res.write(HEADER);
        startTag(res, TAG_LIST_NAME);

        if (remainder != null && module != null) {
            usersHostsService.getFullUsersHostsInfo(owner ? ownerHandler : handler, module, remainder);
        } else {
            usersHostsService.getFullUsersHostsInfo(owner ? ownerHandler : handler);
        }
        endTag(res, TAG_LIST_NAME);
    }

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