/*
 * 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.lang.properties.xml;

import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.Consumer;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.IOUtil;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.xml.NanoXmlUtil;
import net.n3.nanoxml.StdXMLReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Dmitry Avdeev
 *         Date: 7/25/11
 */
public class XmlPropertiesIndex extends FileBasedIndexExtension<XmlPropertiesIndex.Key, String>
  implements FileBasedIndex.FileTypeSpecificInputFilter, DataIndexer<XmlPropertiesIndex.Key, String, FileContent>,
             KeyDescriptor<XmlPropertiesIndex.Key> {

  public final static Key MARKER_KEY = new Key();
  public static final ID<Key,String> NAME = ID.create("xmlProperties");

  private static final EnumeratorStringDescriptor ENUMERATOR_STRING_DESCRIPTOR = new EnumeratorStringDescriptor();
  private static final String HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD = "http://java.sun.com/dtd/properties.dtd";

  @NotNull
  @Override
  public ID<Key, String> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<Key, String, FileContent> getIndexer() {
    return this;
  }

  @NotNull
  @Override
  public KeyDescriptor<Key> getKeyDescriptor() {
    return this;
  }

  @NotNull
  @Override
  public DataExternalizer<String> getValueExternalizer() {
    return ENUMERATOR_STRING_DESCRIPTOR;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return this;
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 2;
  }

  @Override
  public boolean acceptInput(@NotNull VirtualFile file) {
    return true;
  }

  @Override
  public void registerFileTypesUsedForIndexing(@NotNull Consumer<FileType> fileTypeSink) {
    fileTypeSink.consume(XmlFileType.INSTANCE);
  }

  @NotNull
  @Override
  public Map<Key, String> map(@NotNull FileContent inputData) {
    CharSequence text = inputData.getContentAsText();
    if(CharArrayUtil.indexOf(text, HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD, 0) == -1) {
      return Collections.emptyMap();
    }
    MyIXMLBuilderAdapter builder = parse(text, false);
    if (builder == null) return Collections.emptyMap();
    HashMap<Key, String> map = builder.myMap;
    if (builder.accepted) map.put(MARKER_KEY, "");
    return map;
  }

  static boolean isPropertiesFile(XmlFile file) {
    Project project = file.getProject();
    if (DumbService.isDumb(project)) {
      CharSequence contents = file.getViewProvider().getContents();
      return CharArrayUtil.indexOf(contents, HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD, 0) != -1 &&
          isAccepted(contents);
    }
    return !FileBasedIndex.getInstance().processValues(NAME, MARKER_KEY, file.getVirtualFile(),
                                                       new FileBasedIndex.ValueProcessor<String>() {
                                                         @Override
                                                         public boolean process(VirtualFile file, String value) {
                                                           return false;
                                                         }
                                                       }, GlobalSearchScope.allScope(project));
  }

  private static boolean isAccepted(CharSequence bytes) {
    MyIXMLBuilderAdapter builder = parse(bytes, true);
    return builder != null && builder.accepted;
  }

  @Nullable
  private static MyIXMLBuilderAdapter parse(CharSequence text, boolean stopIfAccepted) {
    StdXMLReader reader = new StdXMLReader(CharArrayUtil.readerFromCharSequence(text)) {
      @Override
      public Reader openStream(String publicID, String systemID) throws IOException {
        if (!HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD.equals(systemID)) throw new IOException();
        return new StringReader(" ");
      }
    };
    MyIXMLBuilderAdapter builder = new MyIXMLBuilderAdapter(stopIfAccepted);
    NanoXmlUtil.parse(reader, builder);
    return builder;
  }

  @Override
  public void save(@NotNull DataOutput out, Key value) throws IOException {
    out.writeBoolean(value.isMarker);
    if (value.key != null) {
      IOUtil.writeUTF(out, value.key);
    }
  }

  @Override
  public Key read(@NotNull DataInput in) throws IOException {
    boolean isMarker = in.readBoolean();
    return isMarker ? MARKER_KEY : new Key(IOUtil.readUTF(in));
  }

  @Override
  public int getHashCode(Key value) {
    return value.hashCode();
  }

  @Override
  public boolean isEqual(Key val1, Key val2) {
    return val1.isMarker == val2.isMarker && Comparing.equal(val1.key, val2.key);
  }

  public static class Key {
    final boolean isMarker;
    final String key;

    public Key(String key) {
      this.key = key;
      isMarker = false;
    }

    public Key() {
      isMarker = true;
      key = null;
    }

    @Override
    public int hashCode() {
      return isMarker ? 0 : key.hashCode();
    }

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

      Key key1 = (Key)o;

      if (isMarker != key1.isMarker) return false;
      if (key != null ? !key.equals(key1.key) : key1.key != null) return false;

      return true;
    }
  }

  private static class MyIXMLBuilderAdapter extends NanoXmlUtil.IXMLBuilderAdapter {

    boolean accepted;
    boolean insideEntry;
    String key;
    private final HashMap<Key, String> myMap = new HashMap<Key, String>();
    private final boolean myStopIfAccepted;

    public MyIXMLBuilderAdapter(boolean stopIfAccepted) {
      myStopIfAccepted = stopIfAccepted;
    }

    @Override
    public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr)
      throws Exception {
      if (!accepted) {
        if ("properties".equals(name)) {
          accepted = true;
        }
        else throw NanoXmlUtil.ParserStoppedXmlException.INSTANCE;
      }
      else {
        insideEntry = "entry".equals(name);
      }
      if (myStopIfAccepted) throw NanoXmlUtil.ParserStoppedXmlException.INSTANCE;
    }

    @Override
    public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type)
      throws Exception {
      if (insideEntry && "key".equals(key)) this.key = value;
    }

    @Override
    public void addPCData(Reader reader, String systemID, int lineNr) throws Exception {
      if (insideEntry && key != null) {
        String value = StreamUtil.readTextFrom(reader);
        myMap.put(new Key(key), value);
      }
    }
  }
}
