/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.javaee;

import com.intellij.application.options.PathMacrosImpl;
import com.intellij.application.options.ReplacePathToMacroMap;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.NotNullLazyKey;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.xml.Html5SchemaProvider;
import com.intellij.xml.XmlSchemaProvider;
import com.intellij.xml.util.XmlUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

import java.io.File;
import java.net.URL;
import java.util.*;

@State(name = "ExternalResourceManagerImpl",
       storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml")})
public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx implements PersistentStateComponent<Element> {
  static final Logger LOG = Logger.getInstance(ExternalResourceManagerExImpl.class);

  @NonNls public static final String J2EE_1_3 = "http://java.sun.com/dtd/";
  @NonNls public static final String J2EE_1_2 = "http://java.sun.com/j2ee/dtds/";
  @NonNls public static final String J2EE_NS = "http://java.sun.com/xml/ns/j2ee/";
  @NonNls public static final String JAVAEE_NS = "http://java.sun.com/xml/ns/javaee/";
  private static final String CATALOG_PROPERTIES_ELEMENT = "CATALOG_PROPERTIES";


  private final Map<String, Map<String, String>> myResources = new HashMap<String, Map<String, String>>();
  private final Set<String> myResourceLocations = new HashSet<String>();

  private final Set<String> myIgnoredResources = new HashSet<String>();

  private final AtomicNotNullLazyValue<Map<String, Map<String, Resource>>> myStdResources = new AtomicNotNullLazyValue<Map<String, Map<String, Resource>>>() {

    @NotNull
    @Override
    protected Map<String, Map<String, Resource>> compute() {
      return computeStdResources();
    }
  };

  private String myDefaultHtmlDoctype = HTML5_DOCTYPE_ELEMENT;

  private String myCatalogPropertiesFile;
  private XMLCatalogManager myCatalogManager;
  private static final String HTML5_DOCTYPE_ELEMENT = "HTML5";

  protected Map<String, Map<String, Resource>> computeStdResources() {
    ResourceRegistrarImpl registrar = new ResourceRegistrarImpl();
    for (StandardResourceProvider provider : Extensions.getExtensions(StandardResourceProvider.EP_NAME)) {
      provider.registerResources(registrar);
    }
    StandardResourceEP[] extensions = Extensions.getExtensions(StandardResourceEP.EP_NAME);
    for (StandardResourceEP extension : extensions) {
      registrar.addStdResource(extension.url, extension.version, extension.resourcePath, null, extension.getLoaderForClass());
    }

    myIgnoredResources.addAll(registrar.getIgnored());
    return registrar.getResources();
  }

  private final List<ExternalResourceListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
  @NonNls private static final String RESOURCE_ELEMENT = "resource";
  @NonNls private static final String URL_ATTR = "url";
  @NonNls private static final String LOCATION_ATTR = "location";
  @NonNls private static final String IGNORED_RESOURCE_ELEMENT = "ignored-resource";
  @NonNls private static final String HTML_DEFAULT_DOCTYPE_ELEMENT = "default-html-doctype";
  private static final String DEFAULT_VERSION = null;

  @Override
  public boolean isStandardResource(VirtualFile file) {
    VirtualFile parent = file.getParent();
    return parent != null && parent.getName().equals("standardSchemas");
  }

  @Override
  public boolean isUserResource(VirtualFile file) {
    return myResourceLocations.contains(file.getUrl());
  }

  @Nullable
  static <T> Map<String, T> getMap(@NotNull final Map<String, Map<String, T>> resources,
                                   @Nullable final String version,
                                   final boolean create) {
    Map<String, T> map = resources.get(version);
    if (map == null) {
      if (create) {
        map = ContainerUtil.newHashMap();
        resources.put(version, map);
      }
      else if (version == null || !version.equals(DEFAULT_VERSION)) {
        map = resources.get(DEFAULT_VERSION);
      }
    }

    return map;
  }

  @Override
  public String getResourceLocation(String url) {
    return getResourceLocation(url, DEFAULT_VERSION);
  }

  @Override
  public String getResourceLocation(@NonNls String url, String version) {
    String result = getUserResource(url, version);
    if (result == null) {
      XMLCatalogManager manager = getCatalogManager();
      if (manager != null) {
        result = manager.resolve(url);
      }
    }
    if (result == null) {
      result = getStdResource(url, version);
    }
    if (result == null) {
      result = url;
    }
    return result;
  }

  @Override
  @Nullable
  public String getUserResource(Project project, String url, String version) {
    String resource = getProjectResources(project).getUserResource(url, version);
    return resource == null ? getUserResource(url, version) : resource;
  }

  @Override
  @Nullable
  public String getStdResource(String url, String version) {
    Map<String, Resource> map = getMap(myStdResources.getValue(), version, false);
    if (map != null) {
      Resource resource = map.get(url);
      return resource == null ? null : resource.getResourceUrl();
    }
    else {
      return null;
    }
  }

  @Nullable
  private String getUserResource(String url, String version) {
    Map<String, String> map = getMap(myResources, version, false);
    return map != null ? map.get(url) : null;
  }

  @Override
  public String getResourceLocation(@NonNls String url, @NotNull Project project) {
    String location = getProjectResources(project).getResourceLocation(url);
    return location == null || location.equals(url) ? getResourceLocation(url) : location;
  }

  public String getResourceLocation(@NonNls String url, String version, @NotNull Project project) {
    String location = getProjectResources(project).getResourceLocation(url, version);
    return location == null || location.equals(url) ? getResourceLocation(url, version) : location;
  }

  @Override
  @Nullable
  public PsiFile getResourceLocation(@NotNull @NonNls final String url, @NotNull final PsiFile baseFile, final String version) {
    final XmlFile schema = XmlSchemaProvider.findSchema(url, baseFile);
    if (schema != null) {
      return schema;
    }
    final String location = getResourceLocation(url, version, baseFile.getProject());
    return XmlUtil.findXmlFile(baseFile, location);
  }

  @Override
  public String[] getResourceUrls(FileType fileType, final boolean includeStandard) {
    return getResourceUrls(fileType, DEFAULT_VERSION, includeStandard);
  }

  @Override
  public String[] getResourceUrls(@Nullable final FileType fileType, @NonNls final String version, final boolean includeStandard) {
    final List<String> result = new LinkedList<String>();
    addResourcesFromMap(result, version, myResources);

    if (includeStandard) {
      addResourcesFromMap(result, version, myStdResources.getValue());
    }

    return ArrayUtil.toStringArray(result);
  }

  private static <T> void addResourcesFromMap(final List<String> result,
                                              String version,
                                              Map<String, Map<String, T>> resourcesMap) {
    Map<String, T> resources = getMap(resourcesMap, version, false);
    if (resources == null) return;
    result.addAll(resources.keySet());
  }

  @TestOnly
  public static void addTestResource(final String url, final String location, Disposable parentDisposable) {
    final ExternalResourceManagerExImpl instance = (ExternalResourceManagerExImpl)getInstance();
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        instance.addResource(url, location);
      }
    });
    Disposer.register(parentDisposable, new Disposable() {
      @Override
      public void dispose() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          @Override
          public void run() {
            instance.removeResource(url);
          }
        });
      }
    });
  }
  @Override
  public void addResource(String url, String location) {
    addResource(url, DEFAULT_VERSION, location);
  }

  @Override
  public void addResource(@NonNls String url, @NonNls String version, @NonNls String location) {
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    addSilently(url, version, location);
    fireExternalResourceChanged();
  }

  private void addSilently(String url, String version, String location) {
    final Map<String, String> map = getMap(myResources, version, true);
    assert map != null;
    map.put(url, location);
    myResourceLocations.add(location);
    incModificationCount();
  }

  @Override
  public void removeResource(String url) {
    removeResource(url, DEFAULT_VERSION);
  }

  @Override
  public void removeResource(String url, String version) {
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    Map<String, String> map = getMap(myResources, version, false);
    if (map != null) {
      String location = map.remove(url);
      if (location != null) {
        myResourceLocations.remove(location);
      }
      incModificationCount();
      fireExternalResourceChanged();
    }
  }

  @Override
  public void removeResource(String url, @NotNull Project project) {
    getProjectResources(project).removeResource(url);
  }

  @Override
  public void addResource(@NonNls String url, @NonNls String location, @NotNull Project project) {
    getProjectResources(project).addResource(url, location);
  }

  @Override
  public String[] getAvailableUrls() {
    Set<String> urls = new HashSet<String>();
    for (Map<String, String> map : myResources.values()) {
      urls.addAll(map.keySet());
    }
    return ArrayUtil.toStringArray(urls);
  }

  @Override
  public String[] getAvailableUrls(Project project) {
    return getProjectResources(project).getAvailableUrls();
  }

  @Override
  public void clearAllResources() {
    myResources.clear();
    myIgnoredResources.clear();
  }

  @Override
  public void clearAllResources(Project project) {
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    clearAllResources();
    getProjectResources(project).clearAllResources();
    incModificationCount();
    fireExternalResourceChanged();
  }

  @Override
  public void addIgnoredResource(String url) {
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    addIgnoredSilently(url);
    fireExternalResourceChanged();
  }

  private void addIgnoredSilently(String url) {
    myIgnoredResources.add(url);
    incModificationCount();
  }

  @Override
  public void removeIgnoredResource(String url) {
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    if (myIgnoredResources.remove(url)) {
      incModificationCount();
      fireExternalResourceChanged();
    }
  }

  @Override
  public boolean isIgnoredResource(String url) {
    myStdResources.getValue();  // ensure ignored resources are loaded
    return myIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url);
  }

  private static boolean isImplicitNamespaceDescriptor(String url) {
    for (ImplicitNamespaceDescriptorProvider namespaceDescriptorProvider : Extensions
      .getExtensions(ImplicitNamespaceDescriptorProvider.EP_NAME)) {
      if (namespaceDescriptorProvider.getNamespaceDescriptor(null, url, null) != null) return true;
    }
    return false;
  }

  @Override
  public String[] getIgnoredResources() {
    myStdResources.getValue();  // ensure ignored resources are loaded
    return ArrayUtil.toStringArray(myIgnoredResources);
  }

  @Override
  public long getModificationCount(@NotNull Project project) {
    return getProjectResources(project).getModificationCount();
  }


  @Nullable
  @Override
  public Element getState() {
    Element element = new Element("state");
    final String[] urls = getAvailableUrls();
    for (String url : urls) {
      if (url == null) continue;
      String location = getResourceLocation(url);
      if (location == null) continue;
      final Element e = new Element(RESOURCE_ELEMENT);

      e.setAttribute(URL_ATTR, url);
      e.setAttribute(LOCATION_ATTR, location.replace(File.separatorChar, '/'));
      element.addContent(e);
    }

    final String[] ignoredResources = getIgnoredResources();
    for (String ignoredResource : ignoredResources) {
      final Element e = new Element(IGNORED_RESOURCE_ELEMENT);

      e.setAttribute(URL_ATTR, ignoredResource);
      element.addContent(e);
    }

    if (myDefaultHtmlDoctype != null && !HTML5_DOCTYPE_ELEMENT.equals(myDefaultHtmlDoctype)) {
      final Element e = new Element(HTML_DEFAULT_DOCTYPE_ELEMENT);
      e.setText(myDefaultHtmlDoctype);
      element.addContent(e);
    }
    if (myCatalogPropertiesFile != null) {
      Element properties = new Element(CATALOG_PROPERTIES_ELEMENT);
      properties.setText(myCatalogPropertiesFile);
      element.addContent(properties);
    }
    final ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap();
    PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements);
    macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive);
    return element;
  }

  @Override
  public void loadState(Element element) {
    final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap();
    PathMacrosImpl.getInstanceEx().addMacroExpands(macroExpands);
    macroExpands.substitute(element, SystemInfo.isFileSystemCaseSensitive);

    incModificationCount();
    for (final Object o1 : element.getChildren(RESOURCE_ELEMENT)) {
      Element e = (Element)o1;
      addSilently(e.getAttributeValue(URL_ATTR), DEFAULT_VERSION, e.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar));
    }

    for (final Object o : element.getChildren(IGNORED_RESOURCE_ELEMENT)) {
      Element e = (Element)o;
      addIgnoredSilently(e.getAttributeValue(URL_ATTR));
    }

    Element child = element.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT);
    if (child != null) {
      String text = child.getText();
      if (FileUtil.toSystemIndependentName(text).endsWith(".jar!/resources/html5-schema/html5.rnc")) {
        text = HTML5_DOCTYPE_ELEMENT;
      }
      myDefaultHtmlDoctype = text;
    }
    Element catalogElement = element.getChild(CATALOG_PROPERTIES_ELEMENT);
    if (catalogElement != null) {
      myCatalogPropertiesFile = catalogElement.getTextTrim();
    }
  }


  @Override
  public void addExternalResourceListener(ExternalResourceListener listener) {
    myListeners.add(listener);
  }

  @Override
  public void removeExternalResourceListener(ExternalResourceListener listener) {
    myListeners.remove(listener);
  }

  private void fireExternalResourceChanged() {
    for (ExternalResourceListener listener : myListeners) {
      listener.externalResourceChanged();
    }
  }

  Collection<Map<String, Resource>> getStandardResources() {
    return myStdResources.getValue().values();
  }


  private static final NotNullLazyKey<ExternalResourceManagerExImpl, Project> INSTANCE_CACHE = ServiceManager.createLazyKey(ExternalResourceManagerExImpl.class);

  private static ExternalResourceManagerExImpl getProjectResources(Project project) {
    return INSTANCE_CACHE.getValue(project);
  }

  @Override
  @NotNull
  public String getDefaultHtmlDoctype(@NotNull Project project) {
    final String doctype = getProjectResources(project).myDefaultHtmlDoctype;
    if (XmlUtil.XHTML_URI.equals(doctype)) {
      return XmlUtil.XHTML4_SCHEMA_LOCATION;
    }
    else if (HTML5_DOCTYPE_ELEMENT.equals(doctype)) {
      return Html5SchemaProvider.getHtml5SchemaLocation();
    }
    else {
      return doctype;
    }
  }

  @Override
  public void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project) {
    getProjectResources(project).setDefaultHtmlDoctype(defaultHtmlDoctype);
  }

  @Override
  public String getCatalogPropertiesFile() {
    return myCatalogPropertiesFile;
  }

  @Override
  public void setCatalogPropertiesFile(String filePath) {
    myCatalogManager = null;
    myCatalogPropertiesFile = filePath;
    incModificationCount();
  }

  @Nullable
  private XMLCatalogManager getCatalogManager() {
    if (myCatalogManager == null && myCatalogPropertiesFile != null) {
      myCatalogManager = new XMLCatalogManager(myCatalogPropertiesFile);
    }
    return myCatalogManager;
  }

  private void setDefaultHtmlDoctype(String defaultHtmlDoctype) {
    incModificationCount();

    if (Html5SchemaProvider.getHtml5SchemaLocation().equals(defaultHtmlDoctype)) {
      myDefaultHtmlDoctype = HTML5_DOCTYPE_ELEMENT;
    }
    else {
      myDefaultHtmlDoctype = defaultHtmlDoctype;
    }
    fireExternalResourceChanged();
  }

  @TestOnly
  public static void registerResourceTemporarily(final String url, final String location, Disposable disposable) {
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        getInstance().addResource(url, location);
      }
    });

    Disposer.register(disposable, new Disposable() {
      @Override
      public void dispose() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          @Override
          public void run() {
            getInstance().removeResource(url);
          }
        });
      }
    });
  }

  static class Resource {
    private final String myFile;
    private final ClassLoader myClassLoader;
    private final Class myClass;
    private volatile String myResolvedResourcePath;

    Resource(String _file, Class _class, ClassLoader _classLoader) {
      myFile = _file;
      myClass = _class;
      myClassLoader = _classLoader;
    }

    Resource(String _file, Resource baseResource) {
      this(_file, baseResource.myClass, baseResource.myClassLoader);
    }

    String directoryName() {
      int i = myFile.lastIndexOf('/');
      return i > 0 ? myFile.substring(0, i) : myFile;
    }

    @Nullable
    String getResourceUrl() {
      String resolvedResourcePath = myResolvedResourcePath;
      if (resolvedResourcePath != null) return resolvedResourcePath;

      final URL resource = myClass == null ? myClassLoader.getResource(myFile) : myClass.getResource(myFile);

      if (resource == null) {
        String message = "Cannot find standard resource. filename:" + myFile + " class=" + myClass + ", classLoader:" + myClassLoader;
        if (ApplicationManager.getApplication().isUnitTestMode()) {
          LOG.error(message);
        }
        else {
          LOG.warn(message);
        }

        myResolvedResourcePath = null;
        return null;
      }

      String path = FileUtil.unquote(resource.toString());
      // this is done by FileUtil for windows
      path = path.replace('\\','/');
      myResolvedResourcePath = path;
      return path;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      Resource resource = (Resource)o;

      if (myClassLoader != resource.myClassLoader) return false;
      if (myClass != resource.myClass) return false;
      if (myFile != null ? !myFile.equals(resource.myFile) : resource.myFile != null) return false;

      return true;
    }

    @Override
    public int hashCode() {
      return myFile.hashCode();
    }

    @Override
    public String toString() {
      return myFile + " for " + myClassLoader;
    }
  }
}
