/*
 * 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.openapi.roots.impl.libraries;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ComponentSerializationUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.RootProvider;
import com.intellij.openapi.roots.impl.RootModelImpl;
import com.intellij.openapi.roots.impl.RootProviderBaseImpl;
import com.intellij.openapi.roots.libraries.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

import static com.intellij.openapi.vfs.VirtualFileVisitor.ONE_LEVEL_DEEP;
import static com.intellij.openapi.vfs.VirtualFileVisitor.SKIP_ROOT;

/**
 * @author dsl
 */
public class LibraryImpl extends TraceableDisposable implements LibraryEx.ModifiableModelEx, LibraryEx {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.impl.LibraryImpl");
  @NonNls public static final String LIBRARY_NAME_ATTR = "name";
  @NonNls public static final String LIBRARY_TYPE_ATTR = "type";
  @NonNls public static final String ROOT_PATH_ELEMENT = "root";
  @NonNls public static final String ELEMENT = "library";
  @NonNls public static final String PROPERTIES_ELEMENT = "properties";
  private static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
  private static final String EXCLUDED_ROOTS_TAG = "excluded";
  private String myName;
  private final LibraryTable myLibraryTable;
  private final Map<OrderRootType, VirtualFilePointerContainer> myRoots;
  @Nullable private VirtualFilePointerContainer myExcludedRoots;
  private final JarDirectories myJarDirectories = new JarDirectories();
  private final LibraryImpl mySource;
  private PersistentLibraryKind<?> myKind;
  private LibraryProperties myProperties;

  private final MyRootProviderImpl myRootProvider = new MyRootProviderImpl();
  private final ModifiableRootModel myRootModel;
  private boolean myDisposed;
  private final Disposable myPointersDisposable = Disposer.newDisposable();
  private final JarDirectoryWatcher myRootsWatcher = JarDirectoryWatcherFactory.getInstance().createWatcher(myJarDirectories, myRootProvider);

  LibraryImpl(LibraryTable table, Element element, ModifiableRootModel rootModel) throws InvalidDataException {
    this(table, rootModel, null, element.getAttributeValue(LIBRARY_NAME_ATTR),
         (PersistentLibraryKind<?>)LibraryKind.findById(element.getAttributeValue(LIBRARY_TYPE_ATTR)));
    readProperties(element);
    myJarDirectories.readExternal(element);
    readRoots(element);
    myRootsWatcher.updateWatchedRoots();
  }

  LibraryImpl(String name, @Nullable final PersistentLibraryKind<?> kind, LibraryTable table, ModifiableRootModel rootModel) {
    this(table, rootModel, null, name, kind);
    if (kind != null) {
      myProperties = kind.createDefaultProperties();
    }
  }

  private LibraryImpl(@NotNull LibraryImpl from, LibraryImpl newSource, ModifiableRootModel rootModel) {
    this(from.myLibraryTable, rootModel, newSource, from.myName, from.myKind);
    from.checkDisposed();

    if (from.myKind != null && from.myProperties != null) {
      myProperties = myKind.createDefaultProperties();
      //noinspection unchecked
      myProperties.loadState(from.myProperties.getState());
    }
    for (OrderRootType rootType : getAllRootTypes()) {
      final VirtualFilePointerContainer thisContainer = myRoots.get(rootType);
      final VirtualFilePointerContainer thatContainer = from.myRoots.get(rootType);
      thisContainer.addAll(thatContainer);
    }
    if (from.myExcludedRoots != null) {
      myExcludedRoots = from.myExcludedRoots.clone(myPointersDisposable);
    }
    myJarDirectories.copyFrom(from.myJarDirectories);
  }

  // primary
  private LibraryImpl(LibraryTable table, ModifiableRootModel rootModel, LibraryImpl newSource, String name, @Nullable final PersistentLibraryKind<?> kind) {
    super(new Throwable());
    myLibraryTable = table;
    myRootModel = rootModel;
    mySource = newSource;
    myKind = kind;
    myName = name;
    //init roots depends on my myKind
    myRoots = initRoots();
    Disposer.register(this, myRootsWatcher);
  }

  private Set<OrderRootType> getAllRootTypes() {
    Set<OrderRootType> rootTypes = new HashSet<OrderRootType>();
    rootTypes.addAll(Arrays.asList(OrderRootType.getAllTypes()));
    if (myKind != null) {
      rootTypes.addAll(Arrays.asList(myKind.getAdditionalRootTypes()));
    }
    return rootTypes;
  }

  @Override
  public void dispose() {
    checkDisposed();

    myDisposed = true;
    kill(null);
  }

  private void checkDisposed() {
    if (isDisposed()) {
      throwDisposalError("'" + myName + "' already disposed:");
    }
  }

  @Override
  public boolean isDisposed() {
    return myDisposed;
  }

  @Override
  public String getName() {
    return myName;
  }

  @Override
  @NotNull
  public String[] getUrls(@NotNull OrderRootType rootType) {
    checkDisposed();

    final VirtualFilePointerContainer result = myRoots.get(rootType);
    return result.getUrls();
  }

  @Override
  @NotNull
  public VirtualFile[] getFiles(@NotNull OrderRootType rootType) {
    checkDisposed();

    final List<VirtualFile> expanded = new ArrayList<VirtualFile>();
    for (VirtualFile file : myRoots.get(rootType).getFiles()) {
      if (file.isDirectory()) {
        if (myJarDirectories.contains(rootType, file.getUrl())) {
          collectJarFiles(file, expanded, myJarDirectories.isRecursive(rootType, file.getUrl()));
          continue;
        }
      }
      expanded.add(file);
    }
    return VfsUtilCore.toVirtualFileArray(expanded);
  }

  public static void collectJarFiles(final VirtualFile dir, final List<VirtualFile> container, final boolean recursively) {
    VfsUtilCore.visitChildrenRecursively(dir, new VirtualFileVisitor(SKIP_ROOT, recursively ? null : ONE_LEVEL_DEEP) {
      @Override
      public boolean visitFile(@NotNull VirtualFile file) {
        final VirtualFile jarRoot = file.isDirectory() ? null : StandardFileSystems.getJarRootForLocalFile(file);
        if (jarRoot != null) {
          container.add(jarRoot);
          return false;
        }
        return true;
      }
    });
  }

  @Override
  public void setName(String name) {
    LOG.assertTrue(isWritable());
    myName = name;
  }

  /* you have to commit modifiable model or dispose it by yourself! */
  @Override
  @NotNull
  public ModifiableModelEx getModifiableModel() {
    checkDisposed();
    return new LibraryImpl(this, this, myRootModel);
  }

  @Override
  public Library cloneLibrary(RootModelImpl rootModel) {
    LOG.assertTrue(myLibraryTable == null);
    final LibraryImpl clone = new LibraryImpl(this, null, rootModel);
    clone.myRootsWatcher.updateWatchedRoots();
    return clone;
  }

  @Override
  public List<String> getInvalidRootUrls(OrderRootType type) {
    if (myDisposed) return Collections.emptyList();

    final List<VirtualFilePointer> pointers = myRoots.get(type).getList();
    List<String> invalidPaths = null;
    for (VirtualFilePointer pointer : pointers) {
      if (!pointer.isValid()) {
        if (invalidPaths == null) {
          invalidPaths = new SmartList<String>();
        }
        invalidPaths.add(pointer.getUrl());
      }
    }
    return invalidPaths == null ? Collections.<String>emptyList() : invalidPaths;
  }

  @Override
  public void setProperties(LibraryProperties properties) {
    LOG.assertTrue(isWritable());
    myProperties = properties;
  }

  @Override
  @NotNull
  public RootProvider getRootProvider() {
    return myRootProvider;
  }

  private Map<OrderRootType, VirtualFilePointerContainer> initRoots() {
    Disposer.register(this, myPointersDisposable);

    Map<OrderRootType, VirtualFilePointerContainer> result = new HashMap<OrderRootType, VirtualFilePointerContainer>(4);

    for (OrderRootType rootType : getAllRootTypes()) {
      result.put(rootType, VirtualFilePointerManager.getInstance().createContainer(myPointersDisposable));
    }

    return result;
  }

  @Override
  public void readExternal(Element element) throws InvalidDataException {
    readName(element);
    readProperties(element);
    readRoots(element);
    myJarDirectories.readExternal(element);
    myRootsWatcher.updateWatchedRoots();
  }

  private void readProperties(Element element) {
    final String typeId = element.getAttributeValue(LIBRARY_TYPE_ATTR);
    if (typeId == null) return;

    myKind = (PersistentLibraryKind<?>) LibraryKind.findById(typeId);
    if (myKind == null) return;

    myProperties = myKind.createDefaultProperties();
    final Element propertiesElement = element.getChild(PROPERTIES_ELEMENT);
    if (propertiesElement != null) {
      ComponentSerializationUtil.loadComponentState(myProperties, propertiesElement);
    }
  }

  private void readName(Element element) {
    myName = element.getAttributeValue(LIBRARY_NAME_ATTR);
  }

  private void readRoots(Element element) throws InvalidDataException {
    for (OrderRootType rootType : getAllRootTypes()) {
      final Element rootChild = element.getChild(rootType.name());
      if (rootChild == null) {
        continue;
      }
      VirtualFilePointerContainer roots = myRoots.get(rootType);
      roots.readExternal(rootChild, ROOT_PATH_ELEMENT);
    }
    Element excludedRoot = element.getChild(EXCLUDED_ROOTS_TAG);
    if (excludedRoot != null) {
      getOrCreateExcludedRoots().readExternal(excludedRoot, ROOT_PATH_ELEMENT);
    }
  }

  private VirtualFilePointerContainer getOrCreateExcludedRoots() {
    if (myExcludedRoots == null) {
      myExcludedRoots = VirtualFilePointerManager.getInstance().createContainer(myPointersDisposable);
    }
    return myExcludedRoots;
  }

  //TODO<rv> Remove the next two methods as a temporary solution. Sort in OrderRootType.
  //
  public static List<OrderRootType> sortRootTypes(Collection<OrderRootType> rootTypes) {
    List<OrderRootType> allTypes = new ArrayList<OrderRootType>(rootTypes);
    Collections.sort(allTypes, new Comparator<OrderRootType>() {
      @Override
      public int compare(@NotNull final OrderRootType o1, @NotNull final OrderRootType o2) {
        return o1.name().compareToIgnoreCase(o2.name());
      }
    });
    return allTypes;
  }

  @Override
  public void writeExternal(Element rootElement) throws WriteExternalException {
    checkDisposed();

    Element element = new Element(ELEMENT);
    if (myName != null) {
      element.setAttribute(LIBRARY_NAME_ATTR, myName);
    }
    if (myKind != null) {
      element.setAttribute(LIBRARY_TYPE_ATTR, myKind.getKindId());
      final Object state = myProperties.getState();
      if (state != null) {
        final Element propertiesElement = XmlSerializer.serialize(state, SERIALIZATION_FILTERS);
        if (propertiesElement != null && (!propertiesElement.getContent().isEmpty() || !propertiesElement.getAttributes().isEmpty())) {
          element.addContent(propertiesElement.setName(PROPERTIES_ELEMENT));
        }
      }
    }
    ArrayList<OrderRootType> storableRootTypes = new ArrayList<OrderRootType>();
    storableRootTypes.addAll(Arrays.asList(OrderRootType.getAllTypes()));
    if (myKind != null) {
      storableRootTypes.addAll(Arrays.asList(myKind.getAdditionalRootTypes()));
    }
    for (OrderRootType rootType : sortRootTypes(storableRootTypes)) {
      final VirtualFilePointerContainer roots = myRoots.get(rootType);
      if (roots.size() == 0 && rootType.skipWriteIfEmpty()) continue; //compatibility iml/ipr
      final Element rootTypeElement = new Element(rootType.name());
      roots.writeExternal(rootTypeElement, ROOT_PATH_ELEMENT);
      element.addContent(rootTypeElement);
    }
    if (myExcludedRoots != null && myExcludedRoots.size() > 0) {
      Element excluded = new Element(EXCLUDED_ROOTS_TAG);
      myExcludedRoots.writeExternal(excluded, ROOT_PATH_ELEMENT);
      element.addContent(excluded);
    }
    myJarDirectories.writeExternal(element);
    rootElement.addContent(element);
  }

  private boolean isWritable() {
    return mySource != null;
  }

  @Nullable
  @Override
  public PersistentLibraryKind<?> getKind() {
    return myKind;
  }

  @Override
  public void addExcludedRoot(@NotNull String url) {
    VirtualFilePointerContainer roots = getOrCreateExcludedRoots();
    if (roots.findByUrl(url) == null) {
      roots.add(url);
    }
  }

  @Override
  public boolean removeExcludedRoot(@NotNull String url) {
    if (myExcludedRoots != null) {
      VirtualFilePointer pointer = myExcludedRoots.findByUrl(url);
      if (pointer != null) {
        myExcludedRoots.remove(pointer);
        return true;
      }
    }
    return false;
  }

  @NotNull
  @Override
  public String[] getExcludedRootUrls() {
    return myExcludedRoots != null ? myExcludedRoots.getUrls() : ArrayUtil.EMPTY_STRING_ARRAY;
  }

  @NotNull
  @Override
  public VirtualFile[] getExcludedRoots() {
    return myExcludedRoots != null ? myExcludedRoots.getFiles() : VirtualFile.EMPTY_ARRAY;
  }

  @Override
  public LibraryProperties getProperties() {
    return myProperties;
  }

  @Override
  public void setKind(PersistentLibraryKind<?> kind) {
    LOG.assertTrue(isWritable());
    LOG.assertTrue(myKind == null || myKind == kind, "Library kind cannot be changed from " + myKind + " to " + kind);
    myKind = kind;
  }

  @Override
  public void addRoot(@NotNull String url, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    container.add(url);
  }

  @Override
  public void addRoot(@NotNull VirtualFile file, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    container.add(file);
  }

  @Override
  public void addJarDirectory(@NotNull final String url, final boolean recursive) {
    addJarDirectory(url, recursive, JarDirectories.DEFAULT_JAR_DIRECTORY_TYPE);
  }

  @Override
  public void addJarDirectory(@NotNull final VirtualFile file, final boolean recursive) {
    addJarDirectory(file, recursive, JarDirectories.DEFAULT_JAR_DIRECTORY_TYPE);
  }

  @Override
  public void addJarDirectory(@NotNull final String url, final boolean recursive, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    container.add(url);
    myJarDirectories.add(rootType, url, recursive);
  }

  @Override
  public void addJarDirectory(@NotNull final VirtualFile file, final boolean recursive, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    container.add(file);
    myJarDirectories.add(rootType, file.getUrl(), recursive);
  }

  @Override
  public boolean isJarDirectory(@NotNull final String url) {
    return isJarDirectory(url, JarDirectories.DEFAULT_JAR_DIRECTORY_TYPE);
  }

  @Override
  public boolean isJarDirectory(@NotNull final String url, @NotNull final OrderRootType rootType) {
    return myJarDirectories.contains(rootType, url);
  }

  @Override
  public boolean isValid(@NotNull final String url, @NotNull final OrderRootType rootType) {
    final VirtualFilePointerContainer container = myRoots.get(rootType);
    final VirtualFilePointer fp = container.findByUrl(url);
    return fp != null && fp.isValid();
  }

  @Override
  public boolean removeRoot(@NotNull String url, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    final VirtualFilePointer byUrl = container.findByUrl(url);
    if (byUrl != null) {
      container.remove(byUrl);
      if (myExcludedRoots != null) {
        for (String excludedRoot : myExcludedRoots.getUrls()) {
          if (!isUnderRoots(excludedRoot)) {
            VirtualFilePointer pointer = myExcludedRoots.findByUrl(excludedRoot);
            if (pointer != null) {
              myExcludedRoots.remove(pointer);
            }
          }
        }
      }
      myJarDirectories.remove(rootType, url);
      return true;
    }
    return false;
  }

  private boolean isUnderRoots(@NotNull String url) {
    for (VirtualFilePointerContainer container : myRoots.values()) {
      if (VfsUtilCore.isUnder(url, Arrays.asList(container.getUrls()))) {
        return true;
      }
    }
    return false;
  }

  @Override
  public void moveRootUp(@NotNull String url, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    container.moveUp(url);
  }

  @Override
  public void moveRootDown(@NotNull String url, @NotNull OrderRootType rootType) {
    checkDisposed();
    LOG.assertTrue(isWritable());

    final VirtualFilePointerContainer container = myRoots.get(rootType);
    container.moveDown(url);
  }

  @Override
  public boolean isChanged() {
    return !mySource.equals(this);
  }

  private boolean areRootsChanged(final LibraryImpl that) {
    return !that.equals(this);
    //final OrderRootType[] allTypes = OrderRootType.getAllTypes();
    //for (OrderRootType type : allTypes) {
    //  final String[] urls = getUrls(type);
    //  final String[] thatUrls = that.getUrls(type);
    //  if (urls.length != thatUrls.length) {
    //    return true;
    //  }
    //  for (int idx = 0; idx < urls.length; idx++) {
    //    final String url = urls[idx];
    //    final String thatUrl = thatUrls[idx];
    //    if (!Comparing.equal(url, thatUrl)) {
    //      return true;
    //    }
    //    final Boolean jarDirRecursive = myJarDirectories.get(url);
    //    final Boolean sourceJarDirRecursive = that.myJarDirectories.get(thatUrl);
    //    if (jarDirRecursive == null ? sourceJarDirRecursive != null : !jarDirRecursive.equals(sourceJarDirRecursive)) {
    //      return true;
    //    }
    //  }
    //}
    //return false;
  }

  public Library getSource() {
    return mySource;
  }

  @Override
  public void commit() {
    checkDisposed();

    mySource.commit(this);
    Disposer.dispose(this);
  }

  private void commit(@NotNull LibraryImpl fromModel) {
    if (myLibraryTable != null) {
      ApplicationManager.getApplication().assertWriteAccessAllowed();
    }
    if (!Comparing.equal(fromModel.myName, myName)) {
      myName = fromModel.myName;
      if (myLibraryTable instanceof LibraryTableBase) {
        ((LibraryTableBase)myLibraryTable).fireLibraryRenamed(this);
      }
    }
    myKind = fromModel.getKind();
    myProperties = fromModel.myProperties;
    if (areRootsChanged(fromModel)) {
      disposeMyPointers();
      copyRootsFrom(fromModel);
      myJarDirectories.copyFrom(fromModel.myJarDirectories);
      myRootsWatcher.updateWatchedRoots();
      myRootProvider.fireRootSetChanged();
    }
  }

  private void copyRootsFrom(LibraryImpl fromModel) {
    Map<OrderRootType, VirtualFilePointerContainer> clonedRoots = ContainerUtil.newHashMap();
    for (Map.Entry<OrderRootType, VirtualFilePointerContainer> entry : fromModel.myRoots.entrySet()) {
      OrderRootType rootType = entry.getKey();
      VirtualFilePointerContainer container = entry.getValue();
      VirtualFilePointerContainer clone = container.clone(myPointersDisposable);
      clonedRoots.put(rootType, clone);
    }
    myRoots.clear();
    myRoots.putAll(clonedRoots);

    VirtualFilePointerContainer excludedRoots = fromModel.myExcludedRoots;
    myExcludedRoots = excludedRoots != null ? excludedRoots.clone(myPointersDisposable) : null;
  }

  private void disposeMyPointers() {
    for (VirtualFilePointerContainer container : new THashSet<VirtualFilePointerContainer>(myRoots.values())) {
      container.killAll();
    }
    if (myExcludedRoots != null) {
      myExcludedRoots.killAll();
    }
    Disposer.dispose(myPointersDisposable);
    Disposer.register(this, myPointersDisposable);
  }

  private class MyRootProviderImpl extends RootProviderBaseImpl {
    @Override
    @NotNull
    public String[] getUrls(@NotNull OrderRootType rootType) {
      Set<String> originalUrls = new LinkedHashSet<String>(Arrays.asList(LibraryImpl.this.getUrls(rootType)));
      for (VirtualFile file : getFiles(rootType)) { // Add those expanded with jar directories.
        originalUrls.add(file.getUrl());
      }
      return ArrayUtil.toStringArray(originalUrls);
    }

    @Override
    @NotNull
    public VirtualFile[] getFiles(@NotNull final OrderRootType rootType) {
      return LibraryImpl.this.getFiles(rootType);
    }
  }

  @Override
  public LibraryTable getTable() {
    return myLibraryTable;
  }

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

    final LibraryImpl library = (LibraryImpl)o;

    if (!myJarDirectories.equals(library.myJarDirectories)) return false;
    if (myName != null ? !myName.equals(library.myName) : library.myName != null) return false;
    if (myRoots != null ? !myRoots.equals(library.myRoots) : library.myRoots != null) return false;
    if (myKind != null ? !myKind.equals(library.myKind) : library.myKind != null) return false;
    if (myProperties != null ? !myProperties.equals(library.myProperties) : library.myProperties != null) return false;
    if (!Comparing.equal(myExcludedRoots, library.myExcludedRoots)) return false;

    return true;
  }

  public int hashCode() {
    int result = myName != null ? myName.hashCode() : 0;
    result = 31 * result + (myRoots != null ? myRoots.hashCode() : 0);
    result = 31 * result + myJarDirectories.hashCode();
    return result;
  }

  @NonNls
  @Override
  public String toString() {
    return "Library: name:" + myName + "; jars:" + myJarDirectories + "; roots:" + myRoots.values();
  }

  @Nullable("will return non-null value only for module level libraries")
  public Module getModule() {
    return myRootModel == null ? null : myRootModel.getModule();
  }
}
