package com.atlassian.bitbucket.internal.webhook;

import com.atlassian.applinks.api.ApplicationId;
import com.atlassian.applinks.api.ApplicationLink;
import com.atlassian.applinks.api.ApplicationLinkService;
import com.atlassian.applinks.api.TypeNotInstalledException;
import com.atlassian.fugue.Option;
import com.atlassian.webhooks.api.register.listener.WebHookListenerRegistrationDetails;
import com.atlassian.webhooks.api.register.listener.WebHookListenerRegistrationDetails.ModuleDescriptorRegistrationDetails;
import com.atlassian.webhooks.spi.UriResolver;
import org.slf4j.Logger;

import java.net.URI;
import java.net.URISyntaxException;

import static org.slf4j.LoggerFactory.getLogger;

public class StandardWebHookUriResolver implements UriResolver {

    private static final Logger log = getLogger(StandardWebHookUriResolver.class);

    private final ApplicationLinkService applicationLinkService;

    public StandardWebHookUriResolver(ApplicationLinkService applicationLinkService) {
        this.applicationLinkService = applicationLinkService;

    }

    @Override
    public Option<URI> getUri(WebHookListenerRegistrationDetails listenerRegistrationDetails, URI uri) {
        if (!listenerRegistrationDetails.getModuleDescriptorDetails().map(ModuleDescriptorRegistrationDetails::getPluginKey)
                .getOrElse("").equals(WebHookConstants.PLUGIN_KEY)) {
            return Option.none();
        }

        if ("applink".equals(uri.getScheme())) {
            // translate applink to the service URL
            String applinkId = uri.getHost();
            try {
                ApplicationLink applicationLink = applicationLinkService.getApplicationLink(new ApplicationId(applinkId));

                if (applicationLink != null) {
                    URI applinkUri = applicationLink.getRpcUrl();

                    String path = applinkUri.getPath() + uri.getPath();
                    try {
                        return Option.some(new URI(applinkUri.getScheme(), applinkUri.getUserInfo(),
                                applinkUri.getHost(), applinkUri.getPort(), path, uri.getQuery(), uri.getFragment()));
                    } catch (URISyntaxException e) {
                        log.warn("Error while resolving Applink webhook URI {}", uri, e);
                    }
                }
            } catch (TypeNotInstalledException e) {
                log.warn("Error while resolving Applink webhook URI {}", uri, e);
            }
        }

        // return the URI unchanged
        return Option.option(uri);
    }
}