/*
 * 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.framework.detection.impl;

import com.intellij.framework.detection.DetectedFrameworkDescription;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorIntegerDescriptor;
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntIterator;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author nik
 */
public class DetectedFrameworksData {
  private static final Logger LOG = Logger.getInstance("#com.intellij.framework.detection.impl.DetectedFrameworksData");
  private PersistentHashMap<Integer,TIntHashSet> myExistentFrameworkFiles;
  private final TIntObjectHashMap<TIntHashSet> myNewFiles;
  private final MultiMap<Integer, DetectedFrameworkDescription> myDetectedFrameworks;

  public DetectedFrameworksData(Project project) {
    myDetectedFrameworks = new MultiMap<Integer, DetectedFrameworkDescription>();
    File file = new File(FrameworkDetectorRegistryImpl.getDetectionDirPath() + File.separator + project.getName() + "." + project.getLocationHash() +
                         File.separator + "files");
    myNewFiles = new TIntObjectHashMap<TIntHashSet>();
    try {
      myExistentFrameworkFiles = new PersistentHashMap<Integer, TIntHashSet>(file, EnumeratorIntegerDescriptor.INSTANCE, new TIntHashSetExternalizer());
    }
    catch (IOException e) {
      LOG.info(e);
      PersistentHashMap.deleteFilesStartingWith(file);
      try {
        myExistentFrameworkFiles = new PersistentHashMap<Integer, TIntHashSet>(file, EnumeratorIntegerDescriptor.INSTANCE, new TIntHashSetExternalizer());
      }
      catch (IOException e1) {
        LOG.error(e1);
      }
    }
  }

  public void saveDetected() {
    try {
      myExistentFrameworkFiles.close();
    }
    catch (IOException e) {
      LOG.info(e);
    }
  }

  public Collection<VirtualFile> retainNewFiles(@NotNull Integer detectorId, @NotNull Collection<VirtualFile> files) {
    TIntHashSet oldSet = myNewFiles.get(detectorId);
    if (oldSet == null) {
      oldSet = new TIntHashSet();
      myNewFiles.put(detectorId, oldSet);
    }

    TIntHashSet existentFilesSet = null;
    try {
      existentFilesSet = myExistentFrameworkFiles.get(detectorId);
    }
    catch (IOException e) {
      LOG.info(e);
    }
    final ArrayList<VirtualFile> newFiles = new ArrayList<VirtualFile>();
    TIntHashSet newSet = new TIntHashSet();
    for (VirtualFile file : files) {
      final int fileId = FileBasedIndex.getFileId(file);
      if (existentFilesSet == null || !existentFilesSet.contains(fileId)) {
        newFiles.add(file);
        newSet.add(fileId);
      }
    }
    if (newSet.equals(oldSet)) {
      return Collections.emptyList();
    }
    myNewFiles.put(detectorId, newSet);
    return newFiles;
  }

  public Set<Integer> getDetectorsForDetectedFrameworks() {
    return myDetectedFrameworks.keySet();
  }

  public Collection<? extends DetectedFrameworkDescription> updateFrameworksList(Integer detectorId,
                                                                                 Collection<? extends DetectedFrameworkDescription> frameworks) {
    final Collection<DetectedFrameworkDescription> oldFrameworks = myDetectedFrameworks.remove(detectorId);
    myDetectedFrameworks.putValues(detectorId, frameworks);
    if (oldFrameworks != null) {
      frameworks.removeAll(oldFrameworks);
    }
    return frameworks;
  }

  public void putExistentFrameworkFiles(Integer id, Collection<? extends VirtualFile> files) {
    TIntHashSet set = null;
    try {
      set = myExistentFrameworkFiles.get(id);
    }
    catch (IOException e) {
      LOG.info(e);
    }
    if (set == null) {
      set = new TIntHashSet();
      try {
        myExistentFrameworkFiles.put(id, set);
      }
      catch (IOException e) {
        LOG.info(e);
      }
    }
    for (VirtualFile file : files) {
      set.add(FileBasedIndex.getFileId(file));
    }
  }

  private static class TIntHashSetExternalizer implements DataExternalizer<TIntHashSet> {
    @Override
    public void save(@NotNull DataOutput out, TIntHashSet value) throws IOException {
      out.writeInt(value.size());
      final TIntIterator iterator = value.iterator();
      while (iterator.hasNext()) {
        out.writeInt(iterator.next());
      }
    }

    @Override
    public TIntHashSet read(@NotNull DataInput in) throws IOException {
      int size = in.readInt();
      final TIntHashSet set = new TIntHashSet(size);
      while (size-- > 0) {
        set.add(in.readInt());
      }
      return set;
    }
  }
}
