/*
 * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
 */

package com.intellij.uiDesigner;

import com.intellij.lang.properties.PropertiesUtil;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Pair;
import com.intellij.reference.SoftReference;
import com.intellij.uiDesigner.lw.StringDescriptor;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.uiDesigner.radComponents.RadRootContainer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @author yole
 */
public class StringDescriptorManager {
  private Module myModule;
  private Map<Pair<Locale, String>, SoftReference<PropertiesFile>> myPropertiesFileCache = new HashMap<Pair<Locale, String>, SoftReference<PropertiesFile>>();

  public StringDescriptorManager(final Module module) {
    myModule = module;
  }

  public static StringDescriptorManager getInstance(Module module) {
    return ServiceManager.getService(module, StringDescriptorManager.class);
  }

  @Nullable public String resolve(@NotNull RadComponent component, @Nullable StringDescriptor descriptor) {
    RadRootContainer root = (RadRootContainer) FormEditingUtil.getRoot(component);
    Locale locale = (root != null) ? root.getStringDescriptorLocale() : null;
    return resolve(descriptor, locale);
  }

  @Nullable public String resolve(@Nullable StringDescriptor descriptor, @Nullable Locale locale) {
    if (descriptor == null) {
      return null;
    }

    if (descriptor.getValue() != null) {
      return descriptor.getValue();
    }

    Property prop = resolveToProperty(descriptor, locale);
    if (prop != null) {
      final String value = prop.getUnescapedValue();
      if (value != null) {
        return value;
      }
    }
    // We have to return surrogate string in case if propFile name is invalid or bundle doesn't have specified key
    return "[" + descriptor.getKey() + " / " + descriptor.getBundleName() + "]";
  }

  public Property resolveToProperty(@NotNull StringDescriptor descriptor, @Nullable Locale locale) {
    String propFileName = descriptor.getDottedBundleName();
    Pair<Locale, String> cacheKey = new Pair<Locale, String>(locale, propFileName);
    SoftReference<PropertiesFile> propertiesFileRef = myPropertiesFileCache.get(cacheKey);
    PropertiesFile propertiesFile = (propertiesFileRef == null) ? null : propertiesFileRef.get();
    if (propertiesFile == null || !propertiesFile.isValid()) {
      propertiesFile = PropertiesUtil.getPropertiesFile(propFileName, myModule, locale);
      myPropertiesFileCache.put(cacheKey, new SoftReference<PropertiesFile>(propertiesFile));
    }

    if (propertiesFile != null) {
      final Property propertyByKey = propertiesFile.findPropertyByKey(descriptor.getKey());
      if (propertyByKey != null) {
        return propertyByKey;
      }
    }
    return null;
  }
}

@@ -395,16 +395,121 @@
 l.Pair;%0A
+import com.intellij.openapi.roots.ModuleRootListener;%0Aimport com.intellij.openapi.roots.ModuleRootEvent;%0A
 import c
@@ -715,24 +715,105 @@
 tContainer;%0A
+import com.intellij.util.messages.MessageBus;%0Aimport com.intellij.ProjectTopics;%0A
 import org.j
@@ -1060,16 +1060,22 @@
 private 
+final 
 Map%3CPair
@@ -1260,32 +1260,48 @@
 al Module module
+, MessageBus bus
 ) %7B%0A    myModule
@@ -1311,16 +1311,351 @@
 module;%0A
+    bus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() %7B%0A      public void beforeRootsChange(final ModuleRootEvent event) %7B%0A      %7D%0A%0A      public void rootsChanged(final ModuleRootEvent event) %7B%0A        synchronized(myPropertiesFileCache) %7B%0A          myPropertiesFileCache.clear();%0A        %7D%0A      %7D%0A    %7D);%0A
   %7D%0A%0A  p
@@ -3034,16 +3034,84 @@
 iesFile%3E
+ propertiesFileRef;%0A    synchronized (myPropertiesFileCache) %7B%0A     
  propert
@@ -3160,16 +3160,22 @@
 heKey);%0A
+    %7D%0A
     Prop
@@ -3412,24 +3412,71 @@
 e, locale);%0A
+      synchronized (myPropertiesFileCache) %7B%0A  
       myProp
@@ -3553,24 +3553,32 @@
 tiesFile));%0A
+      %7D%0A
     %7D%0A%0A    i

reset properties file cache on roots changed (IDEADEV-10529)