package com.atlassian.stash.internal.mail;

import com.atlassian.botocss.Botocss;
import com.atlassian.botocss.BotocssStyles;
import com.atlassian.botocss.DocumentFunctions;
import com.atlassian.plugin.spring.AvailableToPlugins;
import com.atlassian.plugin.webresource.UrlMode;
import com.atlassian.plugin.webresource.WebResourceUrlProvider;
import com.atlassian.stash.internal.annotation.Profiled;
import com.atlassian.bitbucket.mail.HtmlCssInliner;
import com.atlassian.bitbucket.nav.NavBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * HtmlCssInliner inlines CSS from plugin modules into HTML.
 *
 * @since 1.3
 */
@AvailableToPlugins(HtmlCssInliner.class)
@Component("htmlCssInliner")
@Profiled
public class HtmlCssInlinerImpl implements HtmlCssInliner {

    /**
     * Images referenced in any injected CSS should be prepended with this token, e.g.:
     * <pre>
     * .afrojack {
     *     background-image: url('$$$$base.resource.url$$$$bitbucket-logo-email-footer.png');
     * }
     * </pre>
     */
    private static final String CSS_RESOURCE_BASE_URL_TOKEN = "$$$$base.resource.url$$$$";

    private final WebResourceUrlProvider webResourceUrlProvider;
    private final BotocssStylesResolver botocssStylesResolver;
    private final NavBuilder navBuilder;

    @Autowired
    public HtmlCssInlinerImpl(WebResourceUrlProvider webResourceUrlProvider, BotocssStylesResolver botocssStylesResolver, NavBuilder navBuilder) {
        this.webResourceUrlProvider = webResourceUrlProvider;
        this.botocssStylesResolver = botocssStylesResolver;
        this.navBuilder = navBuilder;
    }

    /**
     * Inline CSS referred to by the given complete module key into a given String of HTML.
     * This will include any CSS resource descriptors referred to in the module's dependency tree.
     *
     * @param html HTML to perform CSS inlining on
     * @param cssModuleKey Complete module key for plugin module that has CSS script resources and/or dependencies
     * @return HTML with CSS inlined.
     */
    public String inlineCss(String html, String cssModuleKey) {
        BotocssStyles botoCSStylesForModuleKey = botocssStylesResolver.getBotocssStylesForModuleKey(cssModuleKey);
        String injectedStyles = Botocss.inject(html, botoCSStylesForModuleKey, DocumentFunctions.ZERO_INDENT);

        // replace baseUrl token with base static resource URL for the current module. The upshot of this is
        // that all image resources need to be defined in the same <client-resource> as the module key being
        // passed in.
        String staticPluginResourceUrl = webResourceUrlProvider.getStaticPluginResourceUrl(cssModuleKey, "", UrlMode.ABSOLUTE);

        String requestBaseUrl = navBuilder.buildAbsolute();

        String configuredBaseUrl = navBuilder.buildConfigured();

        injectedStyles = StringUtils.replace(injectedStyles,
                CSS_RESOURCE_BASE_URL_TOKEN,
                configuredBaseUrl + staticPluginResourceUrl.substring(requestBaseUrl.length())
        );

        return injectedStyles;
    }

}
