/*
 * Copyright 2006 Sascha Weinreuter
 *
 * 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 org.intellij.plugins.intelliLang.inject.config.ui;

import com.intellij.lang.Language;
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.ui.AncestorListenerAdapter;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.Set;

public final class LanguagePanel extends AbstractInjectionPanel<BaseInjection> {
  private JPanel myRoot;
  private ComboBox<@Nls String> myLanguage;
  private EditorTextField myPrefix;
  private EditorTextField mySuffix;

  public LanguagePanel(Project project, BaseInjection injection) {
    super(injection, project);
    $$$setupUI$$$();

    final String[] languageIDs = ContainerUtil.map2Array(InjectedLanguage.getAvailableLanguages(), String.class, Language::getID);
    Arrays.sort(languageIDs, String::compareToIgnoreCase);

    myLanguage.setModel(new DefaultComboBoxModel<>(languageIDs));
    myLanguage.setRenderer(new ColoredListCellRenderer<>() {
      final Set<String> IDs = Set.of(languageIDs);

      @Override
      protected void customizeCellRenderer(@NotNull JList list, @Nls String s, int index, boolean selected, boolean hasFocus) {
        final SimpleTextAttributes attributes =
          IDs.contains(s) ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.ERROR_ATTRIBUTES;
        append(s, attributes);

        final Language language = InjectedLanguage.findLanguageById(s);
        if (language != null) {
          final FileType fileType = language.getAssociatedFileType();
          if (fileType != null) {
            setIcon(fileType.getIcon());
            append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
            append("(" + fileType.getDescription() + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
          }
        }
      }
    });
    myLanguage.addItemListener(new ItemListener() {
      @Override
      public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
          updateHighlighters();
        }
      }
    });

    myRoot.addAncestorListener(new AncestorListenerAdapter() {
      @Override
      public void ancestorAdded(AncestorEvent event) {
        updateHighlighters();
      }
    });
  }

  void updateHighlighters() {
    final EditorImpl editor = (EditorImpl)myPrefix.getEditor();
    if (editor == null) return;

    final EditorImpl editor2 = (EditorImpl)mySuffix.getEditor();
    assert editor2 != null;

    final Language language = InjectedLanguage.findLanguageById(getLanguage());
    if (language == null) {
      editor.setHighlighter(new LexerEditorHighlighter(new PlainSyntaxHighlighter(), editor.getColorsScheme()));
      editor2.setHighlighter(new LexerEditorHighlighter(new PlainSyntaxHighlighter(), editor.getColorsScheme()));
    }
    else {
      final SyntaxHighlighter s1 = SyntaxHighlighterFactory.getSyntaxHighlighter(language, myProject, null);
      final SyntaxHighlighter s2 = SyntaxHighlighterFactory.getSyntaxHighlighter(language, myProject, null);
      editor.setHighlighter(new LexerEditorHighlighter(s1, editor.getColorsScheme()));
      editor2.setHighlighter(new LexerEditorHighlighter(s2, editor2.getColorsScheme()));
    }
  }

  public @NotNull String getLanguage() {
    return (String)myLanguage.getSelectedItem();
  }

  public void setLanguage(@NlsSafe String id) {
    final DefaultComboBoxModel<String> model = (DefaultComboBoxModel)myLanguage.getModel();
    if (model.getIndexOf(id) == -1 && !id.isEmpty()) {
      model.insertElementAt(id, 0);
    }
    myLanguage.setSelectedItem(id);
    updateHighlighters();
  }

  public String getPrefix() {
    return myPrefix.getText();
  }

  public void setPrefix(String s) {
    if (!myPrefix.getText().equals(s)) {
      myPrefix.setText(s);
    }
  }

  public String getSuffix() {
    return mySuffix.getText();
  }

  public void setSuffix(String s) {
    if (!mySuffix.getText().equals(s)) {
      mySuffix.setText(s);
    }
  }

  @Override
  protected void resetImpl() {
    setLanguage(myOrigInjection.getInjectedLanguageId());
    setPrefix(myOrigInjection.getPrefix());
    setSuffix(myOrigInjection.getSuffix());
  }

  @Override
  protected void apply(BaseInjection i) {
    i.setInjectedLanguageId(getLanguage());
    i.setPrefix(getPrefix());
    i.setSuffix(getSuffix());
  }

  @Override
  public JPanel getComponent() {
    return myRoot;
  }

  private void $$$setupUI$$$() {
  }
}
