package ru.yandex.wmtools.common.service;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import org.jdom.Document;
import org.jdom.Element;

import ru.yandex.common.util.collections.Pair;
import ru.yandex.wmtools.common.data.info.OAuthInfo;
import ru.yandex.wmtools.common.data.info.OAuthScope;
import ru.yandex.wmtools.common.error.BlackboxException;
import ru.yandex.wmtools.common.error.BlackboxProblem;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.InternalProblem;
import ru.yandex.wmtools.common.error.OAuthException;

/**
 * @author avhaliullin
 */
public class OAuthBlackboxService extends AbstractBlackboxService implements OAuthService {
    private String getValue(Element parent, String tagName) throws InternalException {
        Element e = parent.getChild(tagName);
        if (e == null) {
            throw new InternalException(InternalProblem.PROCESSING_ERROR, "Can't parse OAuth element: " + tagName);
        }
        return e.getValue();
    }

    private URL safeGetUrl(String url) {
        try {
            return new URL(url);
        } catch (MalformedURLException e) {
            return null;
        }
    }

    @Override
    public OAuthInfo getOAuthInfo(String token) throws InternalException {
        Pair<BlackboxProblem, Document> res = getResponse(Pair.of(IdentificationMethod.OAUTH, token), Method.OAUTH, null, 2);
        if (!BlackboxProblem.OK.equals(res.first)) {
            throw new BlackboxException(res.getFirst(), "");
        }
        Element rootElement = res.getSecond().getRootElement();
        Element statusElement = rootElement.getChild("status");
        if (!"VALID".equalsIgnoreCase(statusElement.getValue())) {
            throw new OAuthException(statusElement.getValue(), rootElement.getChild("error").getValue());
        }

        Element oAuthElement = rootElement.getChild("OAuth");
        Set<OAuthScope> scope = new HashSet<OAuthScope>();
        for (String s : getValue(oAuthElement, "scope").split(" ")) {
            s = s.trim();
            if (!s.isEmpty() && s.contains(":")) {
                scope.add(new OAuthScope(s));
            }
        }
        return new OAuthInfo(
                Long.parseLong(getValue(oAuthElement, "uid")),
                getValue(oAuthElement, "client_name"),
                safeGetUrl(getValue(oAuthElement, "client_icon")),
                getValue(oAuthElement, "client_id"),
                scope,
                safeGetUrl(getValue(oAuthElement, "client_homepage"))
        );
    }
}
