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

import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
import com.intellij.ui.table.TableView;
import com.intellij.util.Function;
import com.intellij.util.FunctionUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ElementProducer;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import gnu.trove.THashMap;
import gnu.trove.TObjectObjectProcedure;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import java.awt.*;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TableModelEditor<T> implements ElementProducer<T> {
  private final TableView<T> table;
  private final ToolbarDecorator toolbarDecorator;

  private final ItemEditor<T> itemEditor;

  private final MyListTableModel<T> model;

  public TableModelEditor(@NotNull ColumnInfo[] columns, @NotNull ItemEditor<T> itemEditor, @NotNull String emptyText) {
    this(Collections.<T>emptyList(), columns, itemEditor, emptyText);
  }

  /**
   * source will be copied, passed list will not be used directly
   *
   * Implement {@link DialogItemEditor} instead of {@link ItemEditor} if you want provide dialog to edit.
   */
  public TableModelEditor(@NotNull List<T> items, @NotNull ColumnInfo[] columns, @NotNull ItemEditor<T> itemEditor, @NotNull String emptyText) {
    this.itemEditor = itemEditor;

    model = new MyListTableModel<T>(columns, new ArrayList<T>(items), this);
    table = new TableView<T>(model);
    table.setDefaultEditor(Enum.class, ComboBoxTableCellEditor.INSTANCE);
    table.setStriped(true);
    table.setEnableAntialiasing(true);
    preferredScrollableViewportHeightInRows(JBTable.PREFERRED_SCROLLABLE_VIEWPORT_HEIGHT_IN_ROWS);
    new TableSpeedSearch(table);
    if (columns[0].getColumnClass() == Boolean.class && columns[0].getName().isEmpty()) {
      TableUtil.setupCheckboxColumn(table.getColumnModel().getColumn(0));
    }

   boolean needTableHeader = false;
    for (ColumnInfo column : columns) {
      if (!StringUtil.isEmpty(column.getName())) {
        needTableHeader = true;
        break;
      }
    }

    if (!needTableHeader) {
      table.setTableHeader(null);
    }

    table.getEmptyText().setText(emptyText);
    MyRemoveAction removeAction = new MyRemoveAction();
    toolbarDecorator = ToolbarDecorator.createDecorator(table, this).setRemoveAction(removeAction).setRemoveActionUpdater(removeAction);

    if (itemEditor instanceof DialogItemEditor) {
      addDialogActions();
    }
  }

  public TableModelEditor<T> preferredScrollableViewportHeightInRows(int rows) {
    table.setPreferredScrollableViewportSize(new Dimension(200, table.getRowHeight() * rows));
    return this;
  }

  private void addDialogActions() {
    toolbarDecorator.setEditAction(new AnActionButtonRunnable() {
      @Override
      public void run(AnActionButton button) {
        T item = table.getSelectedObject();
        if (item != null) {
          Function<T, T> mutator;
          if (model.isMutable(item)) {
            mutator = FunctionUtil.id();
          }
          else {
            final int selectedRow = table.getSelectedRow();
            mutator = new Function<T, T>() {
              @Override
              public T fun(T item) {
                return model.getMutable(selectedRow, item);
              }
            };
          }
          ((DialogItemEditor<T>)itemEditor).edit(item, mutator, false);
          table.requestFocus();
        }
      }
    }).setEditActionUpdater(new AnActionButtonUpdater() {
      @Override
      public boolean isEnabled(AnActionEvent e) {
        T item = table.getSelectedObject();
        return item != null && ((DialogItemEditor<T>)itemEditor).isEditable(item);
      }
    });

    if (((DialogItemEditor)itemEditor).isUseDialogToAdd()) {
      toolbarDecorator.setAddAction(new AnActionButtonRunnable() {
        @Override
        public void run(AnActionButton button) {
          T item = createElement();
          ((DialogItemEditor<T>)itemEditor).edit(item, new Function<T, T>() {
            @Override
            public T fun(T item) {
              model.addRow(item);
              return item;
            }
          }, true);
        }
      });
    }
  }

  public TableModelEditor<T> disableUpDownActions() {
    toolbarDecorator.disableUpDownActions();
    return this;
  }

  public TableModelEditor<T> enabled(boolean value) {
    table.setEnabled(value);
    return this;
  }

  public static abstract class DataChangedListener<T> implements TableModelListener {
    public abstract void dataChanged(@NotNull ColumnInfo<T, ?> columnInfo, int rowIndex);

    @Override
    public void tableChanged(TableModelEvent e) {
    }
  }

  public TableModelEditor<T> modelListener(@NotNull DataChangedListener<T> listener) {
    model.dataChangedListener = listener;
    model.addTableModelListener(listener);
    return this;
  }

  @NotNull
  public ListTableModel<T> getModel() {
    return model;
  }

  public static abstract class ItemEditor<T> {
    /**
     * Used for "copy" and "in place edit" actions.
     *
     * You must perform deep clone in case of "add" operation, but in case of "in place edit" you should copy only exposed (via column) properties.
     */
    public abstract T clone(@NotNull T item, boolean forInPlaceEditing);

    @NotNull
    /**
     * Class must have empty constructor.
     */
    public abstract Class<T> getItemClass();

    public boolean isRemovable(@NotNull T item) {
      return true;
    }
  }

  public static abstract class DialogItemEditor<T> extends ItemEditor<T> {
    public abstract void edit(@NotNull T item, @NotNull Function<T, T> mutator, boolean isAdd);

    public abstract void applyEdited(@NotNull T oldItem, @NotNull T newItem);

    public boolean isEditable(@NotNull T item) {
      return true;
    }

    public boolean isUseDialogToAdd() {
      return false;
    }
  }

  @NotNull
  public static <T> T cloneUsingXmlSerialization(@NotNull T oldItem, @NotNull T newItem) {
    Element serialized = XmlSerializer.serialize(oldItem, new SkipDefaultValuesSerializationFilters());
    if (!JDOMUtil.isEmpty(serialized)) {
      XmlSerializer.deserializeInto(newItem, serialized);
    }
    return newItem;
  }

  private static final class MyListTableModel<T> extends ListTableModel<T> {
    private List<T> items;
    private final TableModelEditor<T> editor;
    private final THashMap<T, T> modifiedToOriginal = new THashMap<T, T>();
    private DataChangedListener<T> dataChangedListener;

    public MyListTableModel(@NotNull ColumnInfo[] columns, @NotNull List<T> items, @NotNull TableModelEditor<T> editor) {
      super(columns, items);

      this.items = items;
      this.editor = editor;
    }

    @Override
    public void setItems(@NotNull List<T> items) {
      modifiedToOriginal.clear();
      this.items = items;
      super.setItems(items);
    }

    @Override
    public void removeRow(int index) {
      modifiedToOriginal.remove(getItem(index));
      super.removeRow(index);
    }

    @Override
    public void setValueAt(Object newValue, int rowIndex, int columnIndex) {
      if (rowIndex < getRowCount()) {
        @SuppressWarnings("unchecked")
        ColumnInfo<T, Object> column = (ColumnInfo<T, Object>)getColumnInfos()[columnIndex];
        T item = getItem(rowIndex);
        Object oldValue = column.valueOf(item);
        if (column.getColumnClass() == String.class
            ? !Comparing.strEqual(((String)oldValue), ((String)newValue))
            : !Comparing.equal(oldValue, newValue)) {

          column.setValue(getMutable(rowIndex, item), newValue);
          if (dataChangedListener != null) {
            dataChangedListener.dataChanged(column, rowIndex);
          }
        }
      }
    }

    private T getMutable(int rowIndex, T item) {
      if (isMutable(item)) {
        return item;
      }
      else {
        T mutable = editor.itemEditor.clone(item, true);
        modifiedToOriginal.put(mutable, item);
        items.set(rowIndex, mutable);
        return mutable;
      }
    }

    private boolean isMutable(T item) {
      return modifiedToOriginal.containsKey(item);
    }

    public boolean isModified(@NotNull List<T> oldItems) {
      if (items.size() != oldItems.size()) {
        return true;
      }
      else {
        for (int i = 0, size = items.size(); i < size; i++) {
          if (!items.get(i).equals(oldItems.get(i))) {
            return true;
          }
        }
      }

      return false;
    }

    @NotNull
    public List<T> apply() {
      if (modifiedToOriginal.isEmpty()) {
        return items;
      }

      @SuppressWarnings("unchecked")
      final ColumnInfo<T, Object>[] columns = getColumnInfos();
      modifiedToOriginal.forEachEntry(new TObjectObjectProcedure<T, T>() {
        @Override
        public boolean execute(T newItem, @Nullable T oldItem) {
          if (oldItem == null) {
            // it is added item, we don't need to sync
            return true;
          }

          for (ColumnInfo<T, Object> column : columns) {
            if (column.isCellEditable(newItem)) {
              column.setValue(oldItem, column.valueOf(newItem));
            }
          }

          if (editor.itemEditor instanceof DialogItemEditor) {
            ((DialogItemEditor<T>)editor.itemEditor).applyEdited(oldItem, newItem);
          }

          items.set(ContainerUtil.indexOfIdentity(items, newItem), oldItem);
          return true;
        }
      });

      modifiedToOriginal.clear();
      return items;
    }
  }

  public abstract static class EditableColumnInfo<Item, Aspect> extends ColumnInfo<Item, Aspect> {
    public EditableColumnInfo(@NotNull String name) {
      super(name);
    }

    public EditableColumnInfo() {
      super("");
    }

    @Override
    public boolean isCellEditable(Item item) {
      return true;
    }
  }

  @NotNull
  public JComponent createComponent() {
    return toolbarDecorator.addExtraAction(
      new ToolbarDecorator.ElementActionButton(IdeBundle.message("button.copy"), PlatformIcons.COPY_ICON) {
        @Override
        public void actionPerformed(AnActionEvent e) {
          TableUtil.stopEditing(table);

          List<T> selectedItems = table.getSelectedObjects();
          if (selectedItems.isEmpty()) {
            return;
          }

          for (T item : selectedItems) {
            model.addRow(itemEditor.clone(item, false));
          }

          table.requestFocus();
          TableUtil.updateScroller(table, false);
        }
      }
    ).createPanel();
  }

  @Override
  public T createElement() {
    try {
      Constructor<T> constructor = itemEditor.getItemClass().getDeclaredConstructor();
      try {
        constructor.setAccessible(true);
      }
      catch (SecurityException ignored) {
        return itemEditor.getItemClass().newInstance();
      }
      return constructor.newInstance();
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public boolean canCreateElement() {
    return true;
  }

  public boolean isModified(@NotNull List<T> oldItems) {
    return model.isModified(oldItems);
  }

  public void selectItem(@NotNull final T item) {
    table.clearSelection();

    final Ref<T> ref;
    if (model.modifiedToOriginal.isEmpty()) {
      ref = null;
    }
    else {
      ref = Ref.create();
      model.modifiedToOriginal.forEachEntry(new TObjectObjectProcedure<T, T>() {
        @Override
        public boolean execute(T modified, T original) {
          if (item == original) {
            ref.set(modified);
          }
          return ref.isNull();
        }
      });
    }

    table.addSelection(ref == null || ref.isNull() ? item : ref.get());
  }

  @NotNull
  public List<T> apply() {
    return model.apply();
  }

  public void reset(@NotNull List<T> items) {
    model.setItems(new ArrayList<T>(items));
  }

  private class MyRemoveAction implements AnActionButtonRunnable, AnActionButtonUpdater, TableUtil.ItemChecker {
    @Override
    public void run(AnActionButton button) {
      if (TableUtil.doRemoveSelectedItems(table, model, this)) {
        table.requestFocus();
        TableUtil.updateScroller(table, false);
      }
    }

    @Override
    public boolean isOperationApplyable(@NotNull TableModel ignored, int row) {
      T item = model.getItem(row);
      return item != null && itemEditor.isRemovable(item);
    }

    @Override
    public boolean isEnabled(AnActionEvent e) {
      for (T item : table.getSelectedObjects()) {
        if (itemEditor.isRemovable(item)) {
          return true;
        }
      }
      return false;
    }
  }
}