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

package com.intellij.ide.ui.search;

import com.intellij.application.options.CodeStyleSchemesConfigurable;
import com.intellij.application.options.colors.ColorAndFontOptions;
import com.intellij.codeInsight.intention.impl.config.IntentionManagerSettings;
import com.intellij.codeInsight.intention.impl.config.IntentionSettingsConfigurable;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.openapi.application.ApplicationStarter;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.profile.ui.InspectionProfileConfigurable;
import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;

import java.io.IOException;
import java.util.*;

/**
 * User: anna
 * Date: 13-Feb-2006
 */
@SuppressWarnings({"CallToPrintStackTrace", "SynchronizeOnThis"})
public class TraverseUIStarter implements ApplicationStarter {
  private String OUTPUT_PATH;
  @NonNls private static final String OPTIONS = "options";
  @NonNls private static final String CONFIGURABLE = "configurable";
  @NonNls private static final String ID = "id";
  @NonNls private static final String CONFIGURABLE_NAME = "configurable_name";
  @NonNls private static final String OPTION = "option";
  @NonNls private static final String NAME = "name";
  @NonNls private static final String PATH = "path";

  @NonNls
  public String getCommandName() {
    return "traverseUI";
  }


  public void premain(String[] args) {
    OUTPUT_PATH = args[1];
  }

  public void main(String[] args){
    try {
      startup();
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void startup() throws IOException {
    final HashMap<SearchableConfigurable, Set<Pair<String, String>>> options =
      new HashMap<SearchableConfigurable, Set<Pair<String, String>>>();
    SearchUtil.processProjectConfigurables(ProjectManager.getInstance().getDefaultProject(), options);
    Element root = new Element(OPTIONS);
    for (SearchableConfigurable configurable : options.keySet()) {
      Element configurableElement = new Element(CONFIGURABLE);
      final String id = configurable.getId();
      if (id == null) continue;
      configurableElement.setAttribute(ID, id);
      configurableElement.setAttribute(CONFIGURABLE_NAME, configurable.getDisplayName());
      TreeSet<Pair<String, String>> sortedOptions = new TreeSet<Pair<String, String>>(new Comparator<Pair<String, String>>() {
        public int compare(final Pair<String, String> o1, final Pair<String, String> o2) {
          return o1.first.compareTo(o2.first);
        }
      });
      final Set<Pair<String,String>> strings = options.get(configurable);
      for (Pair<String,String> option : strings) {
        if (option == null || option.first == null || option.first.length() == 0) continue;
        sortedOptions.add(Pair.create(option.first, option.second));
      }
      for (Pair<String,String> option : sortedOptions) {
        Element optionElement = new Element(OPTION);
        optionElement.setAttribute(NAME, option.first);
        if (option.second != null) {
          optionElement.setAttribute(PATH, option.second);
        }
        configurableElement.addContent(optionElement);
      }
      if (configurable instanceof InspectionProfileConfigurable){
        processInspectionTools(configurableElement);
      } else if (configurable instanceof IntentionSettingsConfigurable){
        processIntentions(configurableElement);
      } else if (configurable instanceof ColorAndFontOptions){
        processColorAndFontsSettings((ColorAndFontOptions)configurable, configurableElement);
      } else if (configurable instanceof CodeStyleSchemesConfigurable){
        processCodeStyleConfigurable((CodeStyleSchemesConfigurable)configurable, configurableElement);
      }
      root.addContent(configurableElement);
    }
    JDOMUtil.writeDocument(new Document(root), OUTPUT_PATH, "\n");
  }

  private static void processCodeStyleConfigurable(final CodeStyleSchemesConfigurable configurable, final Element configurableElement) {
    final TreeSet<Pair<String, String>> options = new TreeSet<Pair<String, String>>(new Comparator<Pair<String, String>>() {
      public int compare(final Pair<String, String> o1, final Pair<String, String> o2) {
        return o1.first.compareTo(o2.first);
      }
    });
    options.addAll(configurable.processOptions());
    for (Pair<String, String> pair : options) {
      Element optionElement = new Element(OPTION);
      optionElement.setAttribute(NAME, pair.first);
      if (pair.second != null) {
        optionElement.setAttribute(PATH, pair.second);
      }
      configurableElement.addContent(optionElement);
    }
  }

  private static void processColorAndFontsSettings(final ColorAndFontOptions configurable, final Element configurableElement) {
    final Map<String, String> optionsPath = configurable.processListOptions();
    final Map<String, String> result = new TreeMap<String, String>();
    for (String opt : optionsPath.keySet()) {
      final String path = optionsPath.get(opt);
      final Set<String> words = SearchUtil.getProcessedWords(opt);
      for (String word : words) {
        if (word != null){
          result.put(word, path);
        }
      }
    }
    for (String option : result.keySet()) {
      final String path = result.get(option);
      Element optionElement = new Element(OPTION);
      optionElement.setAttribute(NAME, option);
      optionElement.setAttribute(PATH, path);
      configurableElement.addContent(optionElement);
    }
  }

  private void processIntentions(final Element configurableElement) {
    final IntentionManagerSettings intentionManagerSettings = IntentionManagerSettings.getInstance();
    intentionManagerSettings.buildIndex();
     while (!intentionManagerSettings.isIndexBuild()){//wait for index build
      synchronized (this) {
        try {
          wait(100);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
    final TreeSet<String> words = new TreeSet<String>(intentionManagerSettings.getIntentionWords());
    for (String word : words) {
      final List<String> mentionedIntentions = intentionManagerSettings.getFilteredIntentionNames(word);
      appendToolsToPath(mentionedIntentions, word, configurableElement);
    }
  }

  private void processInspectionTools(final Element configurableElement) {
    InspectionToolRegistrar.getInstance().createTools(); //force index building
    while (!InspectionToolRegistrar.isIndexBuild()){//wait for index build
      synchronized (this) {
        try {
          wait(100);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
    final TreeSet<String> words = new TreeSet<String>(InspectionToolRegistrar.getToolWords());
    for (String word : words) {
      final List<String> mentionedInspections = InspectionToolRegistrar.getFilteredToolNames(word);
      appendToolsToPath(mentionedInspections, word, configurableElement);
    }
  }

  private static void appendToolsToPath(final List<String> mentionedInspections, final String word, final Element configurableElement) {
    StringBuffer allInspections = new StringBuffer();
    for (String inspection : mentionedInspections) {
      allInspections.append(allInspections.length() > 0 ? ";" : "").append(inspection);
    }
    Element optionElement = new Element(OPTION);
    optionElement.setAttribute(NAME, word);
    optionElement.setAttribute(PATH, allInspections.toString());
    configurableElement.addContent(optionElement);
  }
}

@@ -5764,32 +5764,39 @@
 %0A  %7D%0A%0A  private 
+static 
 void processInte
@@ -5831,32 +5831,32 @@
 rableElement) %7B%0A
-
     final Intent
@@ -5937,24 +5937,24 @@
 Instance();%0A
+
     intentio
@@ -5988,254 +5988,8 @@
 ();%0A
-     while (!intentionManagerSettings.isIndexBuild())%7B//wait for index build%0A      synchronized (this) %7B%0A        try %7B%0A          wait(100);%0A        %7D%0A        catch (InterruptedException e) %7B%0A          e.printStackTrace();%0A        %7D%0A      %7D%0A    %7D%0A
     

remove threading