/*
 * 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.util.xml.ui;

import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.JBColor;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.*;
import com.intellij.util.xml.highlighting.DomElementAnnotationsManager;
import com.intellij.util.xml.highlighting.DomElementProblemDescriptor;
import com.intellij.util.xml.highlighting.DomElementsProblemsHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
import java.util.List;

/**
 * @author peter
 */
public class ComboControl extends BaseModifiableControl<JComboBox, String> {
  private static final Pair<String, Icon> EMPTY = new ComboBoxItem(" ", null);
  private final Factory<List<Pair<String, Icon>>> myDataFactory;
  private boolean myNullable;
  private final Map<String, Icon> myIcons = new HashMap<String, Icon>();
  private final ItemListener myCommitListener = new ItemListener() {
    @Override
    public void itemStateChanged(ItemEvent e) {
      setModified();
      commit();
    }
  };

  public ComboControl(final GenericDomValue genericDomValue, final Factory<List<Pair<String, Icon>>> dataFactory) {
    this(new DomStringWrapper(genericDomValue), dataFactory);
  }

  public ComboControl(final DomWrapper<String> domWrapper, final Factory<List<Pair<String, Icon>>> dataFactory) {
    super(domWrapper);
    myDataFactory = dataFactory;
    reset();
  }

  public ComboControl(final DomWrapper<String> domWrapper, final Class<? extends Enum> aClass) {
    super(domWrapper);
    myDataFactory = createEnumFactory(aClass);
    reset();
  }

  public final boolean isNullable() {
    return myNullable;
  }

  public final void setNullable(final boolean nullable) {
    myNullable = nullable;
  }

  public ComboControl(final GenericDomValue<?> reference) {
    this(reference, createResolvingFunction(reference));
  }

  public static Factory<List<Pair<String, Icon>>> createResolvingFunction(final GenericDomValue<?> reference) {
    return new Factory<List<Pair<String, Icon>>>() {
      @Override
      public List<Pair<String, Icon>> create() {
        final Converter converter = reference.getConverter();
        if (converter instanceof ResolvingConverter) {
          final AbstractConvertContext context = new AbstractConvertContext() {
            @Override
            @NotNull
            public DomElement getInvocationElement() {
              return reference;
            }
          };
          final ResolvingConverter resolvingConverter = (ResolvingConverter)converter;
          final Collection<Object> variants = resolvingConverter.getVariants(context);
          final List<Pair<String, Icon>> all =
            new ArrayList<Pair<String, Icon>>(ContainerUtil.map(variants, new Function<Object, Pair<String, Icon>>() {
              @Override
              public Pair<String, Icon> fun(final Object s) {
                return Pair.create(ElementPresentationManager.getElementName(s), ElementPresentationManager.getIcon(s));
              }
            }));
          all.addAll(ContainerUtil.map(resolvingConverter.getAdditionalVariants(context), new Function() {
            @Override
            public Object fun(final Object s) {
              return new Pair(s, null);
            }
          }));
          return all;
        }
        return Collections.emptyList();
      }
    };
  }

  public static Factory<List<Pair<String, Icon>>> createPresentationFunction(final Factory<Collection<?>> variantFactory) {
    return new Factory<List<Pair<String, Icon>>>() {
      @Override
      public List<Pair<String, Icon>> create() {

        return ContainerUtil.map(variantFactory.create(), new Function<Object, Pair<String, Icon>>() {
          @Override
          public Pair<String, Icon> fun(final Object s) {
            return Pair.create(ElementPresentationManager.getElementName(s), ElementPresentationManager.getIcon(s));
          }
        });

      }
    };
  }

  static Factory<List<Pair<String, Icon>>> createEnumFactory(final Class<? extends Enum> aClass) {
    return new Factory<List<Pair<String, Icon>>>() {
      @Override
      public List<Pair<String, Icon>> create() {
        return ContainerUtil.map2List(aClass.getEnumConstants(), new Function<Enum, Pair<String, Icon>>() {
          @Override
          public Pair<String, Icon> fun(final Enum s) {
            return Pair.create(NamedEnumUtil.getEnumValueByElement(s), ElementPresentationManager.getIcon(s));
          }
        });
      }
    };
  }

  public static <T extends Enum> JComboBox createEnumComboBox(final Class<T> type) {
    return tuneUpComboBox(new JComboBox(), createEnumFactory(type));
  }

  private static JComboBox tuneUpComboBox(final JComboBox comboBox, Factory<List<Pair<String, Icon>>> dataFactory) {
    final List<Pair<String, Icon>> list = dataFactory.create();
    final Set<String> standardValues = new HashSet<String>();
    for (final Pair<String, Icon> pair : list) {
      comboBox.addItem(new ComboBoxItem(pair));
      standardValues.add(pair.first);
    }
    return initComboBox(comboBox, new Condition<String>() {
      @Override
      public boolean value(final String object) {
        return standardValues.contains(object);
      }
    });
  }

  private static class ComboBoxItem extends Pair<String,Icon> {

    public ComboBoxItem(String first, Icon second) {
      super(first, second);
    }

    public ComboBoxItem(Pair<String,Icon> pair) {
      super(pair.first, pair.second);
    }

    public String toString() {
      return StringUtil.notNullize(first);
    }
  }

  static JComboBox initComboBox(final JComboBox comboBox, final Condition<String> validity) {
    comboBox.setEditable(false);
    comboBox.setPrototypeDisplayValue(new ComboBoxItem("A", null));
    comboBox.setRenderer(new DefaultListCellRenderer() {
      @Override
      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        final Pair<String, Icon> pair = (Pair<String, Icon>)value;
        final String text = pair == null ? null : pair.first;
        setText(text);
        final Dimension dimension = getPreferredSize();
        if (!validity.value(text)) {
          setFont(getFont().deriveFont(Font.ITALIC));
          setForeground(JBColor.RED);
        }
        setIcon(pair == null ? null : pair.second);
        setPreferredSize(new Dimension(-1, dimension.height));
        return this;
      }
    });
    return comboBox;
  }

  @Override
  protected JComboBox createMainComponent(final JComboBox boundedComponent) {
    return initComboBox(boundedComponent == null ? new JComboBox() : boundedComponent, new Condition<String>() {
      @Override
      public boolean value(final String object) {
        return isValidValue(object);
      }
    });
  }

  public boolean isValidValue(final String object) {
    return myNullable && object == EMPTY.first || myIcons.containsKey(object);
  }

  private boolean dataChanged(List<Pair<String, Icon>> newData) {
    final JComboBox comboBox = getComponent();
    final int size = comboBox.getItemCount();
    final List<Pair<String, Icon>> oldData = new ArrayList<Pair<String, Icon>>(size);
    for (int i = 0; i < size; i++) {
      oldData.add((Pair<String, Icon>)comboBox.getItemAt(i));
    }

    if (myNullable) {
      final LinkedList<Pair<String, Icon>> list = new LinkedList<Pair<String, Icon>>(newData);
      list.addFirst(EMPTY);
      newData = list;
    }

    return !newData.equals(oldData);
  }

  @Override
  protected boolean isCommitted() {
    return getComponent().isPopupVisible() || super.isCommitted();
  }

  @Override
  protected void doReset() {
    final List<Pair<String, Icon>> data = myDataFactory.create();
    final JComboBox comboBox = getComponent();
    comboBox.removeItemListener(myCommitListener);
    try {
      if (!dataChanged(data)) {
        super.doReset();
        return;
      }

      final String oldValue = getValue();
      myIcons.clear();
      comboBox.removeAllItems();
      if (myNullable) {
        comboBox.addItem(EMPTY);
      }
      for (final Pair<String, Icon> s : data) {
        comboBox.addItem(new ComboBoxItem(s));
        myIcons.put(s.first, s.second);
      }
      setValue(oldValue);
      super.doReset();
    }
    finally {
      comboBox.addItemListener(myCommitListener);
    }
  }

  @Override
  @Nullable
  protected final String getValue() {
    final Pair<String, Icon> pair = (Pair<String, Icon>)getComponent().getSelectedItem();
    return pair == null || pair == EMPTY ? null : pair.first;
  }

  @Override
  protected final void setValue(final String value) {
    final JComboBox component = getComponent();
    if (!isValidValue(value)) {
      component.setEditable(true);
    }
    component.setSelectedItem(new ComboBoxItem(value, myIcons.get(value)));
    component.setEditable(false);
  }


  @Override
  protected void updateComponent() {
    final DomElement domElement = getDomElement();
    if (domElement == null || !domElement.isValid()) return;

    final JComboBox comboBox = getComponent();

    final Project project = getProject();
    ApplicationManager.getApplication().invokeLater(new Runnable() {
      @Override
      public void run() {
        if (!project.isOpen()) return;
        if (!getDomWrapper().isValid()) return;

        final DomElement domElement = getDomElement();
        if (domElement == null || !domElement.isValid()) return;

        final DomElementAnnotationsManager manager = DomElementAnnotationsManager.getInstance(project);
        final DomElementsProblemsHolder holder = manager.getCachedProblemHolder(domElement);
        final List<DomElementProblemDescriptor> errorProblems = holder.getProblems(domElement);
        final List<DomElementProblemDescriptor> warningProblems = holder.getProblems(domElement, true, HighlightSeverity.WARNING);

        Color background = getDefaultBackground();
        comboBox.setToolTipText(null);

        if (errorProblems.size() > 0) {
          background = getErrorBackground();
          comboBox.setToolTipText(TooltipUtils.getTooltipText(errorProblems));
        }
        else if (warningProblems.size() > 0) {
          background = getWarningBackground();
          comboBox.setToolTipText(TooltipUtils.getTooltipText(warningProblems));
        }

            final Pair<String, Icon> pair = (Pair<String, Icon>)comboBox.getSelectedItem();
            final String s = pair == null ? null : pair.first;
            background = s != null && s.trim().length() > 0 ? getDefaultBackground() : background;

        comboBox.setBackground(background);
        comboBox.getEditor().getEditorComponent().setBackground(background);
      }
    });

  }
}
