/*
 * Copyright 2000-2009 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.application.options.codeStyle;

import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NonNls;

import javax.swing.*;
import java.awt.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class CodeStyleMainPanel extends JPanel {
  private final CardLayout myLayout = new CardLayout();
  private final JPanel mySettingsPanel = new JPanel(myLayout);

  private final Map<String, NewCodeStyleSettingsPanel> mySettingsPanels = new HashMap<String, NewCodeStyleSettingsPanel>();

  private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
  private final CodeStyleSchemesModel myModel;
  private final CodeStyleSettingsPanelFactory myFactory;

  @NonNls
  private static final String WAIT_CARD = "CodeStyleSchemesConfigurable.$$$.Wait.placeholder.$$$";


  public CodeStyleMainPanel(CodeStyleSchemesModel model, CodeStyleSettingsPanelFactory factory) {
    super(new BorderLayout());
    myModel = model;
    myFactory = factory;

    final CodeStyleSchemesPanel schemesPanel = new CodeStyleSchemesPanel(model);

    model.addListener(new CodeStyleSettingsListener(){
      public void currentSchemeChanged(final Object source) {
        if (source != schemesPanel) {
          schemesPanel.onSelectedSchemeChanged();
        }
        onCurrentSchemeChanged();
      }

      public void schemeListChanged() {
        schemesPanel.resetSchemesCombo();
      }

      public void currentSettingsChanged() {
        ensureCurrentPanel().onSomethingChanged();
      }

      public void usePerProjectSettingsOptionChanged() {
        schemesPanel.usePerProjectSettingsOptionChanged();
      }

      public void schemeChanged(final CodeStyleScheme scheme) {
        ensurePanel(scheme).resetFromClone();
      }
    });

    addWaitCard();

    add(schemesPanel.getPanel(), BorderLayout.NORTH);

    DetailsComponent detComp = new DetailsComponent();
    detComp.setPaintBorder(false);
    detComp.setContent(mySettingsPanel);
    detComp.setText(getDisplayName());

    add(detComp.getComponent(), BorderLayout.CENTER);

    schemesPanel.resetSchemesCombo();
    schemesPanel.onSelectedSchemeChanged();
    onCurrentSchemeChanged();

  }

  private void addWaitCard() {
    JPanel waitPanel = new JPanel(new BorderLayout());
    JLabel label = new JLabel(ApplicationBundle.message("label.loading.page.please.wait"));
    label.setHorizontalAlignment(SwingConstants.CENTER);
    waitPanel.add(label, BorderLayout.CENTER);
    label.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    waitPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    mySettingsPanel.add(WAIT_CARD, waitPanel);
  }

  public void onCurrentSchemeChanged() {
    myLayout.show(mySettingsPanel, WAIT_CARD);

    myAlarm.cancelAllRequests();
    final Runnable request = new Runnable() {
      public void run() {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            ensureCurrentPanel().onSomethingChanged();
            myLayout.show(mySettingsPanel, myModel.getSelectedScheme().getName());
          }
        });
      }
    };
    myAlarm.addRequest(request, 200);
  }

  public NewCodeStyleSettingsPanel[] getPanels() {
    final Collection<NewCodeStyleSettingsPanel> panels = mySettingsPanels.values();
    return panels.toArray(new NewCodeStyleSettingsPanel[panels.size()]);
  }

  public boolean isModified() {
    final NewCodeStyleSettingsPanel[] panels = getPanels();
    for (NewCodeStyleSettingsPanel panel : panels) {
      if (panel.isModified()) return true;
    }
    return false;
  }

  public void reset() {
    clearPanels();
    onCurrentSchemeChanged();
  }

  private void clearPanels() {
    for (NewCodeStyleSettingsPanel panel : mySettingsPanels.values()) {
      panel.dispose();
    }
    mySettingsPanels.clear();
  }

  public void apply() {
    final NewCodeStyleSettingsPanel[] panels = getPanels();
    for (NewCodeStyleSettingsPanel panel : panels) {
      if (panel.isModified()) panel.apply();
    }
  }

  @NonNls
  public String getHelpTopic() {
    NewCodeStyleSettingsPanel selectedPanel = ensureCurrentPanel();
    if (selectedPanel == null) {
      return "reference.settingsdialog.IDE.globalcodestyle";
    }
    return selectedPanel.getHelpTopic();
  }

  private NewCodeStyleSettingsPanel ensureCurrentPanel() {
    return ensurePanel(myModel.getSelectedScheme());
  }

  private NewCodeStyleSettingsPanel ensurePanel(final CodeStyleScheme scheme) {
    String name = scheme.getName();
    if (!mySettingsPanels.containsKey(name)) {
      NewCodeStyleSettingsPanel panel = myFactory.createPanel(scheme);
      panel.reset();
      panel.setModel(myModel);
      mySettingsPanels.put(name, panel);
      mySettingsPanel.add(scheme.getName(), panel);
    }

    return mySettingsPanels.get(name);
  }

  public String getDisplayName() {
    return ensureCurrentPanel().getDisplayName();
  }

  public void disposeUIResources() {
    myAlarm.cancelAllRequests();
    clearPanels();
  }

  public boolean isModified(final CodeStyleScheme scheme) {
    if (!mySettingsPanels.containsKey(scheme.getName())) {
      return false;
    }

    return mySettingsPanels.get(scheme.getName()).isModified();
  }
}

@@ -5663,39 +5663,39 @@
 urn 
-ensureCurrentPanel().getDisplay
+myModel.getSelectedScheme().get
 Name

fix default project code style settings: do not create anything on getDisplayName