package com.atlassian.stash.internal.plugin;

import com.atlassian.plugin.Plugin;
import com.atlassian.plugin.PluginAccessor;
import com.atlassian.plugin.event.PluginEventListener;
import com.atlassian.plugin.event.events.PluginDisabledEvent;
import com.atlassian.plugin.event.events.PluginEnabledEvent;
import com.atlassian.util.concurrent.ResettableLazyReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.TreeSet;

import static java.lang.String.format;
import static java.util.stream.Collectors.toCollection;

// I18nStateHasher is based on the reference implementation in:
// https://bitbucket.org/atlassian/atlassian-refapp/pull-requests/151/refappdev-57-updating-wrm-to-3529/diff
@Component
public class I18nStateHasher {
    private final ResettableLazyReference<String> hashLazyRef;

    @Autowired
    public I18nStateHasher(PluginAccessor pluginAccessor) {
        hashLazyRef = new ResettableLazyReference<String>() {
            @Override
            protected String create() throws Exception {

                Set<String> pluginVersions = pluginAccessor.getEnabledPlugins().stream()
                        .filter(I18nStateHasher.this::pluginContainsI18nResources)
                        .map(plugin -> format("%s v.%s", plugin.getKey(),
                                plugin.getPluginInformation().getVersion()))
                        // TreeSet is used to ensure consistent hashing if same inputs are in different order
                        .collect(toCollection(TreeSet::new));

                return Integer.toString(pluginVersions.hashCode());
            }
        };
    }

    public String get() {
        return hashLazyRef.get();
    }

    @PluginEventListener
    public void onPluginDisabled(PluginDisabledEvent event) {
        if (pluginContainsI18nResources(event.getPlugin())) {
            hashLazyRef.reset();
        }
    }

    @PluginEventListener
    public void onPluginEnabled(PluginEnabledEvent event) {
        if (pluginContainsI18nResources(event.getPlugin())) {
            hashLazyRef.reset();
        }
    }

    private boolean pluginContainsI18nResources(Plugin plugin) {
        return plugin.getResourceDescriptors().stream()
                .anyMatch(rd -> rd.getType().equals("i18n"));
    }

}