/*
 * 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.uiDesigner.actions;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.uiDesigner.CutCopyPasteSupport;
import com.intellij.uiDesigner.FormEditingUtil;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.lw.IProperty;
import com.intellij.uiDesigner.propertyInspector.properties.BindingProperty;
import com.intellij.uiDesigner.propertyInspector.properties.IntroComponentProperty;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.uiDesigner.radComponents.RadContainer;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author yole
 */
public class DuplicateComponentsAction extends AbstractGuiEditorAction {
  private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.actions.DuplicateComponentsAction");

  public DuplicateComponentsAction() {
    super(true);
  }

  protected void actionPerformed(final GuiEditor editor, final List<RadComponent> selection, final AnActionEvent e) {
    FormEditingUtil.remapToActionTargets(selection);
    RadContainer parent = FormEditingUtil.getSelectionParent(selection);
    assert parent != null;
    List<RadComponent> duplicates = new ArrayList<RadComponent>();
    Map<RadComponent, RadComponent> duplicateMap = new HashMap<RadComponent, RadComponent>();
    TIntHashSet insertedRows = new TIntHashSet();
    boolean incrementRow = true;
    if (selection.size() > 1 && canDuplicate(selection, false) && FormEditingUtil.getSelectionBounds(selection).width == 1) {
      incrementRow = false;
    }
    for(RadComponent c: selection) {
      final int row = c.getConstraints().getCell(incrementRow);
      int rowSpan = c.getConstraints().getSpan(incrementRow);
      int insertIndex = parent.indexOfComponent(c);
      if (parent.getLayoutManager().isGrid()) {
        if (!insertedRows.contains(row) && !isSpaceBelowEmpty(c, incrementRow)) {
          insertedRows.add(row);
          parent.getGridLayoutManager().copyGridCells(parent, parent, incrementRow, row, rowSpan, row + rowSpan);
        }
      }

      List<RadComponent> copyList = CutCopyPasteSupport.copyComponents(editor, Collections.singletonList(c));
      if (copyList != null) {
        RadComponent copy = copyList.get(0);
        if (parent.getLayoutManager().isGrid()) {
          copy.getConstraints().setCell(incrementRow, row + rowSpan + parent.getGridLayoutManager().getGapCellCount());
          copy.getConstraints().setSpan(incrementRow, rowSpan);
        }
        parent.addComponent(copy, insertIndex+1);
        fillDuplicateMap(duplicateMap, c, copy);
        duplicates.add(copy);
      }
    }
    adjustDuplicates(duplicateMap);
    FormEditingUtil.selectComponents(editor, duplicates);
  }

  private static void fillDuplicateMap(Map<RadComponent, RadComponent> duplicates, final RadComponent c, final RadComponent copy) {
    duplicates.put(c, copy);
    if (c instanceof RadContainer) {
      LOG.assertTrue(copy instanceof RadContainer);
      final RadContainer container = (RadContainer)c;
      final RadContainer containerCopy = (RadContainer)copy;
      for(int i=0; i<container.getComponentCount(); i++) {
        fillDuplicateMap(duplicates, container.getComponent(i), containerCopy.getComponent(i));
      }
    }
  }

  private static void adjustDuplicates(final Map<RadComponent, RadComponent> duplicates) {
    for(RadComponent c: duplicates.keySet()) {
      RadComponent copy = duplicates.get(c);
      if (c.getBinding() != null) {
        String binding = BindingProperty.getDefaultBinding(copy);
        new BindingProperty(c.getProject()).setValueEx(copy, binding);
        copy.setDefaultBinding(true);
      }
      for(IProperty prop: copy.getModifiedProperties()) {
        if (prop instanceof IntroComponentProperty) {
          final IntroComponentProperty componentProperty = (IntroComponentProperty)prop;
          String copyValue = componentProperty.getValue(copy);
          for(RadComponent original: duplicates.keySet()) {
            if (original.getId().equals(copyValue)) {
              componentProperty.setValueEx(copy, duplicates.get(original).getId());
            }
          }
        }
      }
    }
  }

  private static boolean isSpaceBelowEmpty(final RadComponent component, boolean incrementRow) {
    final GridConstraints constraints = component.getConstraints();
    int startRow = constraints.getCell(incrementRow) + constraints.getSpan(incrementRow);
    int endRow = constraints.getCell(incrementRow) + constraints.getSpan(incrementRow)*2 +
                 component.getParent().getGridLayoutManager().getGapCellCount();
    if (endRow > component.getParent().getGridCellCount(incrementRow)) {
      return false;
    }
    for(int row=startRow; row < endRow; row++) {
      for(int col=constraints.getCell(!incrementRow); col < constraints.getCell(!incrementRow) + constraints.getSpan(!incrementRow); col++) {
        if (component.getParent().getComponentAtGrid(incrementRow, row, col) != null) {
          return false;
        }
      }
    }
    return true;
  }

  protected void update(@NotNull GuiEditor editor, final ArrayList<RadComponent> selection, final AnActionEvent e) {
    FormEditingUtil.remapToActionTargets(selection);
    final RadContainer parent = FormEditingUtil.getSelectionParent(selection);
    e.getPresentation().setEnabled(parent != null && (parent.getLayoutManager().isGrid() || parent.getLayoutManager().isIndexed()));
    // The action is enabled in any of the following cases:
    // 1) a single component is selected;
    // 2) all selected components have rowspan=1
    // 3) all selected components have the same row and rowspan
    if (selection.size() > 1 && parent != null && parent.getLayoutManager().isGrid()) {
      e.getPresentation().setEnabled(canDuplicate(selection, true) || canDuplicate(selection, false));
    }
  }

  private static boolean canDuplicate(final List<RadComponent> selection, final boolean incrementRow) {
    int aRow = selection.get(0).getConstraints().getCell(incrementRow);
    int aRowSpan = selection.get(0).getConstraints().getSpan(incrementRow);
    for(int i=1; i<selection.size(); i++) {
      final RadComponent c = selection.get(i);
      if (c.getConstraints().getSpan(incrementRow) > 1 || aRowSpan > 1) {
        if (c.getConstraints().getCell(incrementRow) != aRow || c.getConstraints().getSpan(incrementRow) != aRowSpan) {
          return false;
        }
      }
    }
    return true;
  }

  @Override @Nullable
  protected String getCommandName() {
    return UIDesignerBundle.message("command.duplicate");
  }
}
