package ru.yandex.wmconsole.verification;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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

import ru.yandex.common.framework.user.UserInfo;
import ru.yandex.wmconsole.data.VerificationStateEnum;
import ru.yandex.wmconsole.data.info.FreeVerificationInfo;
import ru.yandex.wmconsole.data.info.UsersHostsInfo;
import ru.yandex.wmconsole.util.WwwUtil;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.service.SidsBlackboxService;

/**
 * @author ailyin
 */
public class AutoVerifier implements Verifier {
    private static final Logger log = LoggerFactory.getLogger(AutoVerifier.class);

    private SidsBlackboxService sidsBlackboxService;

    @Override
    public UsersHostsInfo verify(UsersHostsInfo info) {
        log.debug("Trying to autoverify " + info.getHostName() + " for user " + info.getUserId() +
                " using passport info...");
        if (isApplicableForAutoVerify(info)) {
            return UsersHostsInfo.createVerifiedNow(info, VerificationTypeEnum.AUTO);
        } else {
            return UsersHostsInfo.createNotVerifiedNow(info,
                    VerificationStateEnum.NOT_APPLICABLE_FOR_AUTO_VERIFICATION);
        }
    }

    @Override
    public UsersHostsInfo cancel(UsersHostsInfo info) {
        throw new UnsupportedOperationException("not supported");
    }

    private boolean isApplicableForAutoVerify(UsersHostsInfo info) {
        try {
            Map<Integer, String> logins = getServiceLogins(info.getUserInfo().getUserId());
            for (AutoVerificationUnit unit : AutoVerificationUnit.listAll()) {
                String serviceLogin = logins.get(unit.getServiceId());
                if (serviceLogin != null && !serviceLogin.isEmpty()) {
                    String login = unit.isCheckLoginAtService() ? serviceLogin : info.getUserInfo().getLogin();
                    String hostName = info.getHostName().toLowerCase();
                    String rightHostName = login.toLowerCase() + unit.getDomain();
                    if (hostName.equals(rightHostName) ||
                            (unit.isWwwPrefixAllowed() && WwwUtil.equalsIgnoreWww(hostName, rightHostName))) {
                        return true;
                    }
                }
            }
        } catch (InternalException e) {
            //ignore
        }
        return false;
    }

    public List<FreeVerificationInfo> getHostsApplicableForAutoVerify(UserInfo userInfo) {
        try {
            List<FreeVerificationInfo> verifications = new ArrayList<FreeVerificationInfo>();
            Map<Integer, String> logins = getServiceLogins(userInfo.getUserId());
            for (AutoVerificationUnit unit : AutoVerificationUnit.listAll()) {
                String serviceLogin = logins.get(unit.getServiceId());
                if (serviceLogin != null && !serviceLogin.isEmpty()) {
                    String login = unit.isCheckLoginAtService() ? serviceLogin : userInfo.getLogin();
                    verifications.add(new FreeVerificationInfo(login.toLowerCase() + unit.getDomain()));
                }
            }
            return verifications;
        } catch (InternalException e) {
            return new ArrayList<FreeVerificationInfo>();
        }
    }

    private Map<Integer, String> getServiceLogins(long userId) throws InternalException {
        List<Integer> sids = new ArrayList<Integer>();
        for (AutoVerificationUnit unit : AutoVerificationUnit.listAll()) {
            sids.add(unit.getServiceId());
        }
        return sidsBlackboxService.getServiceLogins(userId, sids.toArray(new Integer[sids.size()]));
    }

    @Required
    public void setSidsBlackboxService(SidsBlackboxService sidsBlackboxService) {
        this.sidsBlackboxService = sidsBlackboxService;
    }
}
