/*
 * Copyright 2003-2012 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 jetbrains.mps.ide.ui.dialogs.properties.roots.editors;

import com.intellij.icons.AllIcons.Modules;
import com.intellij.ui.DarculaColors;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.roots.IconActionComponent;
import com.intellij.ui.roots.ResizingWrapper;
import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.persistence.ModelRoot;
import org.jetbrains.mps.openapi.ui.persistence.ModelRootEntry;
import org.jetbrains.mps.openapi.ui.persistence.ModelRootEntry.ModelRootEntryListener;
import org.jetbrains.mps.openapi.ui.persistence.ModelRootEntryEditor;
import org.jetbrains.mps.openapi.ui.persistence.ModelRootEntryExt;

import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventListener;

import static java.awt.GridBagConstraints.EAST;
import static java.awt.GridBagConstraints.HORIZONTAL;
import static java.awt.GridBagConstraints.NONE;
import static java.awt.GridBagConstraints.NORTHWEST;
import static java.awt.GridBagConstraints.RELATIVE;

/**
 * A container for a single model root entry
 */
public final class ModelRootEntryContainer implements ModelRootEntryListener {
  static final Color SOURCES_COLOR = new JBColor(new Color(0x0A50A1), DarculaColors.BLUE);
  static final Color EXCLUDED_COLOR = new JBColor(new Color(0x992E00), DarculaColors.RED);
  static final Color TESTS_COLOR = new Color(0x008C2E);
  static final Color SELECTED_CONTENT_COLOR = new Color(0xF0F9FF);
  private static final Color SELECTED_HEADER_COLOR = new JBColor(new Color(0xDEF2FF), UIUtil.getPanelBackground().darker());
  private static final Color HEADER_COLOR = new JBColor(new Color(0xF5F5F5), Gray._82);
  private static final Color CONTENT_COLOR = new JBColor(Color.WHITE, UIUtil.getPanelBackground());
  private static final Color UNSELECTED_TEXT_COLOR = Gray._51;

  private final ModelRootEntry myModelRootEntry;
  protected ModelRootEntryEditor myEditor;
  private EventDispatcher<ContentEntryEditorListener> myEventDispatcher;
  private boolean myIsSelected = false;

  protected JPanel myMainPanel;
  private JComponent myHeader;
  private JComponent myDetailsComponent;
  private JComponent myBottom;
  private JLabel myHeaderLabel;
  private JBLabel myDetailsLabel;

  public ModelRootEntryContainer(@NotNull ModelRootEntry modelRootEntry) {
    myModelRootEntry = modelRootEntry;
    myModelRootEntry.addModelRootEntryListener(this);
    myEventDispatcher = EventDispatcher.create(ContentEntryEditorListener.class);
  }

  public ModelRootEntry getModelRootEntry() {
    return myModelRootEntry;
  }

  public ModelRoot getModelRoot() {
    return myModelRootEntry.getModelRoot();
  }

  private void initUI() {
    myMainPanel = new JPanel(new GridBagLayout());
    myMainPanel.setOpaque(false);
    myMainPanel.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        myIsSelected = true;
        myEventDispatcher.getMulticaster().focused(ModelRootEntryContainer.this);
      }

      @Override
      public void mouseEntered(MouseEvent e) {
        if (!myIsSelected) {
          setSelected(true);
        }
      }

      @Override
      public void mouseExited(MouseEvent e) {
        if (!myIsSelected) {
          setSelected(false);
        }
      }
    });

    myHeader = createHeader();
    myMainPanel.add(myHeader, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, new JBInsets(2,2,0,2), 0, 0));

    myDetailsComponent = createDetailsComponent();
    myMainPanel.add(myDetailsComponent, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, HORIZONTAL, new JBInsets(0,2,0,2), 0, 0));

    myBottom = new JPanel(new BorderLayout());
    myBottom.add(Box.createVerticalStrut(3), BorderLayout.NORTH);
    myMainPanel.add(myBottom, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, HORIZONTAL, new JBInsets(0,2,0,2), 0, 0));

    setFocused(false);
  }

  protected JComponent createHeader() {
    final JPanel panel = new JPanel(new GridBagLayout());
    myHeaderLabel = new JBLabel(myModelRootEntry.getModelRoot().toString());

    myHeaderLabel.setFont(myHeaderLabel.getFont().deriveFont(Font.BOLD));
    myHeaderLabel.setOpaque(false);
    final IconActionComponent deleteIconComponent = new IconActionComponent(Modules.DeleteContentRoot,
                                                                            Modules.DeleteContentRootRollover,
                                                                            "Delete Model Root",
                                                                            () -> myEventDispatcher.getMulticaster().delete(ModelRootEntryContainer.this));
    panel.add(myHeaderLabel, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 1.0, NORTHWEST, HORIZONTAL, new Insets(0, 2, 0, 0), 0, 0));
    panel.add(deleteIconComponent, new GridBagConstraints(1, RELATIVE, 1, 1, 0.0, 1.0, EAST, NONE, new Insets(0, 0, 0, 2), 0, 0));
//    FilePathClipper.install(myHeaderLabel, wrapper);
    return panel;
  }

  public JComponent getComponent() {
    if (myMainPanel == null) {
      initUI();
    }
    return myMainPanel;
  }

  public void setFocused(boolean isFocused) {
    myIsSelected = isFocused;
    setSelected(isFocused);
  }

  protected void setSelected(boolean selected) {
    if (selected) {
      myHeader.setBackground(SELECTED_HEADER_COLOR);
//      myMainPanel.setBackground(UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground() : SELECTED_CONTENT_COLOR);
      myDetailsComponent.setBackground(UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground() : SELECTED_CONTENT_COLOR);
      myBottom.setBackground(SELECTED_HEADER_COLOR);
      if (myModelRootEntry instanceof ModelRootEntryExt) {
        ((ModelRootEntryExt) myModelRootEntry).resetForegroundColor();
      }
    }
    else {
      myHeader.setBackground(HEADER_COLOR);
//      myMainPanel.setBackground(CONTENT_COLOR);
      myDetailsComponent.setBackground(CONTENT_COLOR);
      myBottom.setBackground(HEADER_COLOR);
      if (myModelRootEntry instanceof ModelRootEntryExt) {
        ((ModelRootEntryExt) myModelRootEntry).setForegroundColor(UNSELECTED_TEXT_COLOR);
      }
    }
    if (!myModelRootEntry.isValid()) {
      myHeader.setBackground(Color.PINK);
    }
  }

  public void addContentEntryEditorListener(ContentEntryEditorListener listener) {
    myEventDispatcher.addListener(listener);
  }

  public ModelRootEntryEditor getEditor() {
    return myModelRootEntry.getEditor();
  }

  protected ModelRootEntryEditor createEditor() {
    return myModelRootEntry.getEditor();
  }

  public void updateUI() {
    myHeaderLabel.setText(myModelRootEntry.getModelRoot().toString());
    if (myDetailsLabel != null) {
      myDetailsLabel.setText(myModelRootEntry.getDetailsText());
    } else {
      myMainPanel.remove(myDetailsComponent);
      if (myModelRootEntry instanceof ModelRootEntryExt) {
        myDetailsComponent = ((ModelRootEntryExt) myModelRootEntry).getDetailsComponent();
      }
      myMainPanel.add(myDetailsComponent, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, HORIZONTAL, new JBInsets(0,2,0,2), 0, 0));
      myMainPanel.revalidate();
    }
  }

  protected JComponent createDetailsComponent() {
    JBPanel panel = new JBPanel(new GridBagLayout());

    JComponent configurableComponent = null;
    if (myModelRootEntry instanceof ModelRootEntryExt) {
      configurableComponent = ((ModelRootEntryExt) myModelRootEntry).getDetailsComponent();
    }
    if (configurableComponent == null) {
      myDetailsLabel = new JBLabel(myModelRootEntry.getDetailsText());
      myDetailsLabel.setOpaque(false);
      panel.add(myDetailsLabel, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 1.0, NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 2, 0, 0), 0, 0));
    } else {
      panel.add(configurableComponent, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 1.0, NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 2, 0, 0), 0, 0));
    }

    return panel;
  }

  @Override
  public void fireDataChanged() {
    updateUI();
  }

  public interface ContentEntryEditorListener extends EventListener {
    void focused(ModelRootEntryContainer entry);
    void delete(ModelRootEntryContainer entry);
    void dataChanged(ModelRootEntryContainer entry);
  }
}
