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

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Couple;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Util;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.palette.ComponentItem;
import com.intellij.uiDesigner.palette.Palette;
import com.intellij.uiDesigner.radComponents.*;
import com.intellij.uiDesigner.shared.XYLayoutManager;

import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

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

  private final static int HORIZONTAL_GRID = 1;
  private final static int VERTICAL_GRID = 2;
  private final static int GRID = 3;
  /**
   * TODO[anton,vova]: most likely should be equal to "xy grid step" when available
   */
  private static final int GRID_TREMOR = 5;

  private GridBuildUtil() {
  }

  public static void breakGrid(final GuiEditor editor) {
    final ArrayList<RadComponent> selection = FormEditingUtil.getSelectedComponents(editor);
    if (selection.size() != 1){
      return;
    }
    if (!(selection.get(0) instanceof RadContainer)) {
      return;
    }
    final RadContainer container = (RadContainer)selection.get(0);
    if (
      container instanceof RadScrollPane ||
      container instanceof RadSplitPane ||
      container instanceof RadTabbedPane
    ){
      return;
    }

    final RadContainer parent = container.getParent();

    if (parent instanceof RadRootContainer) {
      editor.getRootContainer().setMainComponentBinding(container.getBinding());
    }

    // XY can be broken only if its parent is also XY.
    // In other words, breaking of XY is a deletion of unnecessary intermediate panel
    if (container.isXY() && !parent.isXY()) {
      return;
    }

    if (parent != null && parent.isXY()) {
      // parent is XY
      // put the contents of the container into 'parent' and remove 'container'

      final int dx = container.getX();
      final int dy = container.getY();

      while (container.getComponentCount() > 0) {
        final RadComponent component = container.getComponent(0);
        component.shift(dx, dy);
        parent.addComponent(component);
      }

      parent.removeComponent(container);
    }
    else {
      // container becomes XY
      final XYLayoutManager xyLayout = new XYLayoutManagerImpl();
      container.setLayout(xyLayout);
      xyLayout.setPreferredSize(container.getSize());
    }

    editor.refreshAndSave(true);
  }

  public static void convertToVerticalGrid(final GuiEditor editor){
    convertToGridImpl(editor, VERTICAL_GRID);
  }

  public static void convertToHorizontalGrid(final GuiEditor editor){
    convertToGridImpl(editor, HORIZONTAL_GRID);
  }

  public static void convertToGrid(final GuiEditor editor){
    convertToGridImpl(editor, GRID);
  }

  private static void convertToGridImpl(final GuiEditor editor, final int gridType) {
    final boolean createNewContainer;

    final RadContainer parent;
    final RadComponent[] componentsToConvert;
    {
      final ArrayList<RadComponent> selection = FormEditingUtil.getSelectedComponents(editor);
      if (selection.size() == 0) {
        // root container selected
        final RadRootContainer rootContainer = editor.getRootContainer();
        if (rootContainer.getComponentCount() < 2) {
          // nothing to convert
          return;
        }

        componentsToConvert = new RadComponent[rootContainer.getComponentCount()];
        for (int i = 0; i < componentsToConvert.length; i++) {
          componentsToConvert[i] = rootContainer.getComponent(i);
        }
        parent = rootContainer;
        createNewContainer = true;
      }
      else if (selection.size() == 1 && selection.get(0) instanceof RadContainer) {
        parent = (RadContainer)selection.get(0);
        componentsToConvert = new RadComponent[parent.getComponentCount()];
        for (int i = 0; i < componentsToConvert.length; i++) {
          componentsToConvert[i] = parent.getComponent(i);
        }
        createNewContainer = false;
      }
      else {
        componentsToConvert = selection.toArray(new RadComponent[selection.size()]);
        parent = selection.get(0).getParent();
        createNewContainer = true;
      }
    }

    if (!parent.isXY()) {
      // only components in XY can be layed out in grid
      return;
    }
    for (int i = 1; i < componentsToConvert.length; i++) {
      final RadComponent component = componentsToConvert[i];
      if (component.getParent() != parent) {
        return;
      }
    }

    final GridLayoutManager gridLayoutManager;
    if (componentsToConvert.length == 0) {
      // we convert empty XY panel to grid
      gridLayoutManager = new GridLayoutManager(1,1);
    }
    else {
      if (gridType == VERTICAL_GRID) {
        gridLayoutManager = createOneDimensionGrid(componentsToConvert, true);
      }
      else if (gridType == HORIZONTAL_GRID) {
        gridLayoutManager = createOneDimensionGrid(componentsToConvert, false);
      }
      else if (gridType == GRID) {
        gridLayoutManager = createTwoDimensionGrid(componentsToConvert);
      }
      else {
        throw new IllegalArgumentException("invalid grid type: " + gridType);
      }
    }

    for (final RadComponent component : componentsToConvert) {
      if (component instanceof RadContainer) {
        final LayoutManager layout = ((RadContainer)component).getLayout();
        if (layout instanceof XYLayoutManager) {
          ((XYLayoutManager)layout).setPreferredSize(component.getSize());
        }
      }
    }

    if (createNewContainer) {
      // we should create a new panel

      final Module module = editor.getModule();
      final ComponentItem panelItem = Palette.getInstance(editor.getProject()).getPanelItem();
      final RadContainer newContainer = new RadContainer(editor, FormEditingUtil.generateId(editor.getRootContainer()));
      newContainer.setLayout(gridLayoutManager);
      newContainer.init(editor, panelItem);

      for (RadComponent componentToConvert : componentsToConvert) {
        newContainer.addComponent(componentToConvert);
      }

      final Point topLeftPoint = getTopLeftPoint(componentsToConvert);
      newContainer.setLocation(topLeftPoint);

      final Point bottomRightPoint = getBottomRightPoint(componentsToConvert);
      final Dimension size = new Dimension(bottomRightPoint.x - topLeftPoint.x, bottomRightPoint.y - topLeftPoint.y);
      Util.adjustSize(newContainer.getDelegee(), newContainer.getConstraints(), size);
      newContainer.getDelegee().setSize(size);

      parent.addComponent(newContainer);

      FormEditingUtil.clearSelection(editor.getRootContainer());
      newContainer.setSelected(true);

      // restore binding of main component
      {
        final String mainComponentBinding = editor.getRootContainer().getMainComponentBinding();
        if (mainComponentBinding != null && parent instanceof RadRootContainer) {
          newContainer.setBinding(mainComponentBinding);
          editor.getRootContainer().setMainComponentBinding(null);
        }
      }
    }
    else {
      // convert entire 'parent' to grid

      parent.setLayout(gridLayoutManager);

      FormEditingUtil.clearSelection(editor.getRootContainer());
      parent.setSelected(true);
    }

    editor.refreshAndSave(true);
  }

  private static GridLayoutManager createOneDimensionGrid(final RadComponent[] selection, final boolean isVertical){
    Arrays.sort(
      selection,
      new Comparator<RadComponent>() {
        public int compare(final RadComponent o1, final RadComponent o2){
          final Rectangle bounds1 = o1.getBounds();
          final Rectangle bounds2 = o2.getBounds();

          if (isVertical) {
            return (bounds1.y + bounds1.height / 2) - (bounds2.y + bounds2.height / 2);
          }
          else {
            return (bounds1.x + bounds1.width / 2) - (bounds2.x + bounds2.width / 2);
          }
        }
      }
    );

    for (int i = 0; i < selection.length; i++) {
      final RadComponent component = selection[i];
      final GridConstraints constraints = component.getConstraints();
      if (isVertical) {
        constraints.setRow(i);
        constraints.setColumn(0);
      }
      else {
        constraints.setRow(0);
        constraints.setColumn(i);
      }
      constraints.setRowSpan(1);
      constraints.setColSpan(1);
    }

    final GridLayoutManager gridLayoutManager;
    if (isVertical) {
      gridLayoutManager = new GridLayoutManager(selection.length, 1);
    }
    else {
      gridLayoutManager = new GridLayoutManager(1, selection.length);
    }
    return gridLayoutManager;
  }

  /**
   * @param x array of <code>X</code> coordinates of components that should be layed out in a grid.
   * This is input/output parameter.
   *
   * @param y array of <code>Y</code> coordinates of components that should be layed out in a grid.
   * This is input/output parameter.
   *
   * @param rowSpans output parameter.
   *
   * @param colSpans output parameter.
   *
   * @return pair that says how many (rows, columns) are in the composed grid.
   */
  public static Couple<Integer> layoutInGrid(
    final int[] x,
    final int[] y,
    final int[] rowSpans,
    final int[] colSpans
  ){
    LOG.assertTrue(x.length == y.length);
    LOG.assertTrue(y.length == colSpans.length);
    LOG.assertTrue(colSpans.length == rowSpans.length);

    for (int i = 0; i < x.length; i++) {
      colSpans[i] = Math.max(colSpans[i], 1);
      rowSpans[i] = Math.max(rowSpans[i], 1);

      if (colSpans[i] > GRID_TREMOR * 4) {
        colSpans[i] -= GRID_TREMOR * 2;
        x[i] += GRID_TREMOR;
      }
      if (rowSpans[i] > GRID_TREMOR * 4) {
        rowSpans[i] -= GRID_TREMOR * 2;
        y[i] += GRID_TREMOR;
      }
    }


    return Couple.of(
      new Integer(Util.eliminate(y, rowSpans, null)),
      new Integer(Util.eliminate(x, colSpans, null))
    );
  }

  private static GridLayoutManager createTwoDimensionGrid(final RadComponent[] selection){
    final int[] x = new int[selection.length];
    final int[] y = new int[selection.length];
    final int[] colSpans = new int[selection.length];
    final int[] rowSpans = new int[selection.length];

    for (int i = selection.length - 1; i >= 0; i--) {
      x[i] = selection[i].getX();
      y[i] = selection[i].getY();
      rowSpans[i] = selection[i].getHeight();
      colSpans[i] = selection[i].getWidth();
    }

    final Couple<Integer> pair = layoutInGrid(x, y, rowSpans, colSpans);
    for (int i = 0; i < selection.length; i++) {
      final RadComponent component = selection[i];
      final GridConstraints constraints = component.getConstraints();

      constraints.setRow(y[i]);
      constraints.setRowSpan(rowSpans[i]);

      constraints.setColumn(x[i]);
      constraints.setColSpan(colSpans[i]);
    }

    return new GridLayoutManager(pair.first.intValue(), pair.second.intValue());
  }

  /**
   * Find top left point of component group, i.e. (minimum X of all components; minimum Y of all components)
   * @param components array should contain at least one element
   */
  private static Point getTopLeftPoint(final RadComponent[] components){
    LOG.assertTrue(components.length > 0);

    final Point point = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
    for (final RadComponent component : components) {
      point.x = Math.min(component.getX(), point.x);
      point.y = Math.min(component.getY(), point.y);
    }

    return point;
  }

  /**
   * Find bottom right point of component group, i.e. (maximum (x + width) of all components; maximum (y + height) of all components)
   * @param components array should contain at least one element
   */
  private static Point getBottomRightPoint(final RadComponent[] components){
    LOG.assertTrue(components.length > 0);

    final Point point = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
    for (final RadComponent component : components) {
      point.x = Math.max(component.getX() + component.getWidth(), point.x);
      point.y = Math.max(component.getY() + component.getHeight(), point.y);
    }

    return point;
  }
}
