/*******************************************************************************
 * Copyright (c) 2001, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20060504   128984 pmoogk@ca.ibm.com - Peter Moogk
 *******************************************************************************/
package org.eclipse.wst.command.internal.env.ui.dialog;

import java.util.Arrays;
import java.util.Iterator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.command.internal.env.common.StringUtils;
import org.eclipse.wst.common.environment.Choice;


/**
 * A dialog to display one or more errors to the user, as contained in an
 * <code>Status</code> object. If an error contains additional detailed
 * information then a Details button is automatically supplied, which shows or
 * hides an error details viewer when pressed by the user.
 *  
 */
public class MessageDialog extends Dialog
{
  protected Composite parent;

  /**
   * Reserve room for this many list items.
   */
  protected static final int LIST_ITEM_COUNT = 7;

  /**
   * The Details button.
   */
  protected Button detailsButton;

  /**
   * The title of the dialog.
   */
  protected String title;

  /**
   * The message to display.
   */
  protected String message;

  /**
   * The SWT list control that displays the error details.
   */
  protected List list;
  protected Text details;

  /**
   * Indicates whether the error details viewer is currently created.
   */
  protected boolean listCreated = false;
  protected boolean detailsCreated = false;

  /**
   * Filter mask for determining which status items to display.
   */
  protected int displayMask = 0xFFFF;

  /**
   * The main status object.
   */
  protected IStatus status;
  
  private Point savedSize = null;

  /**
   * List of the main error object's detailed errors (element type: <code>Status</code>).
   */
  protected java.util.List statusList;
  /**
   * Creates an error dialog. Note that the dialog will have no visual
   * representation (no widgets) until it is told to open.
   * <p>
   * Normally one should use <code>openError</code> to create and open one of
   * these. This constructor is useful only if the error object being displayed
   * contains child items <it>and</it> you need to specify a mask which will
   * be used to filter the displaying of these children.
   * </p>
   * 
   * @param parentShell
   *            the shell under which to create this dialog
   * @param dialogTitle
   *            the title to use for this dialog, or <code>null</code> to
   *            indicate that the default title should be used
   * @param message
   *            the message to show in this dialog, or <code>null</code> to
   *            indicate that the error's message should be shown as the
   *            primary message
   * @param status
   *            the error to show to the user
   * @param displayMask
   *            the mask to use to filter the displaying of child items, as per
   *            <code>Status.matches</code>
   */
  public MessageDialog(
    Shell parentShell,
    String dialogTitle,
    String message,
    IStatus status,
    int displayMask)
  {
    super(parentShell);
      this.title = dialogTitle == null ? JFaceResources.getString("Problem_Occurred") : //$NON-NLS-1$
  dialogTitle;
    this.message = message == null ? status.getMessage() : JFaceResources.format("Reason", new Object[] { message, status.getMessage()}); //$NON-NLS-1$
    this.status = status;
    statusList = Arrays.asList(status.getChildren());
    this.displayMask = displayMask;
    setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);
  }
  /*
   * (non-Javadoc) Method declared on Dialog. Handles the pressing of the Ok or
   * Details button in this dialog. If the Ok button was pressed then close
   * this dialog. If the Details button was pressed then toggle the displaying
   * of the error details area. Note that the Details button will only be
   * visible if the error being displayed specifies child details.
   */
  protected void buttonPressed(int id)
  {
    if (id == StatusDialogConstants.DETAILS_ID)
    { // was the details button pressed?
      toggleDetailsArea();
    }
    else
    {
      super.buttonPressed(id);
    }
  }
  /*
   * (non-Javadoc) Method declared in Window.
   */
  protected void configureShell(Shell shell)
  {
    super.configureShell(shell);
    shell.setText(title);
  }
  /*
   * (non-Javadoc) This should also be overwritten Method declared on Dialog.
   */
  protected void createButtonsForButtonBar(Composite parent)
  {
    // create OK and Details buttons
    createButton(
      parent,
      StatusDialogConstants.OK_ID,
      IDialogConstants.OK_LABEL,
      true);
    if (status.isMultiStatus() || status.getException() != null )
    {
      detailsButton =
        createButton(
          parent,
          StatusDialogConstants.DETAILS_ID,
          IDialogConstants.SHOW_DETAILS_LABEL,
          false);
    }
    
    parent.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ));
  }

  /*
   * This is one of the few methods that needs to be overwritten by the
   * subclasses. The image names can be found in the Dialog class
   */
  protected Image getDialogImage()
  {
    // create image
    return PlatformUI.getWorkbench().getDisplay().getSystemImage(SWT.ICON_INFORMATION);
  }

  /*
   * (non-Javadoc) Method declared on Dialog. Creates and returns the contents
   * of the upper part of the dialog (above the button bar).
   */
  protected Control createDialogArea(Composite parent)
  {
    this.parent = parent;

    // create composite
    Composite composite = (Composite) super.createDialogArea(parent);
    Composite imageAndLabel = new Composite(composite, SWT.NONE);
    GridLayout gl = new GridLayout();
    gl.numColumns = 2;
    imageAndLabel.setLayout(gl);
    imageAndLabel.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
    composite.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ));
    
    // create image
    Image image = getDialogImage();
    if (image != null)
    {
      Label label = new Label(imageAndLabel, 0);
      image.setBackground(label.getBackground());
      label.setImage(image);
      label.setLayoutData(
        new GridData(
          GridData.HORIZONTAL_ALIGN_CENTER
            | GridData.VERTICAL_ALIGN_BEGINNING));
    }

    // create message
    if (message != null)
    {
      Text text = new Text(imageAndLabel, SWT.READ_ONLY|SWT.WRAP);
      text.setText(message);
      GridData data =
        new GridData(
          GridData.GRAB_HORIZONTAL
            | GridData.GRAB_VERTICAL
            | GridData.HORIZONTAL_ALIGN_FILL
            | GridData.VERTICAL_ALIGN_CENTER);
      data.widthHint =
        convertHorizontalDLUsToPixels(
          IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
     
      text.setLayoutData(data);
      text.setFont(parent.getFont());
    }

    return composite;
  }

  protected List createDropDownList(Composite parent)
  {
    // create the list
    list = new List(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);

    // fill the list
    populateList(list);

    GridData data =
      new GridData(
        GridData.HORIZONTAL_ALIGN_FILL
          | GridData.GRAB_HORIZONTAL
          | GridData.VERTICAL_ALIGN_FILL
          | GridData.GRAB_VERTICAL);
    data.heightHint = list.getItemHeight() * LIST_ITEM_COUNT;
    list.setLayoutData(data);
    listCreated = true;
    return list;
  }
  protected Text createDropDownDetails(Composite parent)
  {
    details = new Text(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY | SWT.WRAP );
    //details.setEditable(false);
    Color color = parent.getShell().getDisplay().getSystemColor( SWT.COLOR_WHITE );
    details.setBackground(color);
    populateDetails(details, status, 0);
    GridData data =
      new GridData(
        GridData.HORIZONTAL_ALIGN_FILL
          | GridData.GRAB_HORIZONTAL
          | GridData.VERTICAL_ALIGN_FILL
          | GridData.GRAB_VERTICAL);
    
    details.setLayoutData(data);
    details.setSelection(0);
    detailsCreated = true;
    return details;
  }
  /*
   * (non-Javadoc) Method declared on Window.
   */
  /**
   * Extends <code>Window.open()</code>. Opens an error dialog to display
   * the error. If you specified a mask to filter the displaying of these
   * children, the error dialog will only be displayed if there is at least one
   * child status matching the mask.
   */
  public int open()
  {
    if (shouldDisplay(status, displayMask))
    {
      return super.open();
    }
    return 0;
  }
  /**
   * This essentially does the work of a factory Opens an error dialog to
   * display the given error. Use this method if the error object being
   * displayed does not contain child items, or if you wish to display all such
   * items without filtering.
   * 
   * @param parent
   *            the parent shell of the dialog, or <code>null</code> if none
   * @param dialogTitle
   *            the title to use for this dialog, or <code>null</code> to
   *            indicate that the default title should be used
   * @param message
   *            the message to show in this dialog, or <code>null</code> to
   *            indicate that the error's message should be shown as the
   *            primary message
   * @param status
   *            the error to show to the user
   * @return the code of the button that was pressed that resulted in this
   *         dialog closing. This will be <code>Dialog.OK</code> if the OK
   *         button was pressed, or <code>Dialog.CANCEL</code> if this
   *         dialog's close window decoration or the ESC key was used.
   */
  public static int openMessage(
    Shell parent,
    String dialogTitle,
    String message,
    IStatus status)
  {

    switch (status.getSeverity())
    {
      case IStatus.INFO :
        return openInfo(
          parent,
          dialogTitle,
          message,
          status,
          IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
      case IStatus.WARNING :
        return openWarning(
          parent,
          dialogTitle,
          message,
          status,
          IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
      default :
        return openError(
          parent,
          dialogTitle,
          message,
          status,
          IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
    }

  }

  public static int openMessage(
    Shell parent,
    String dialogTitle,
    String message,
    IStatus status,
    Choice[] options)
  {

    return openOptions(
      parent,
      dialogTitle,
      message,
      status,
      IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR,
      options);
  }

  /**
   * Opens an error dialog to display the given error. Use this method if the
   * error object being displayed contains child items <it>and</it> you wish
   * to specify a mask which will be used to filter the displaying of these
   * children. The error dialog will only be displayed if there is at least one
   * child status matching the mask.
   * 
   * @param parentShell
   *            the parent shell of the dialog, or <code>null</code> if none
   * @param dialogTitle
   *            the title to use for this dialog, or <code>null</code> to
   *            indicate that the default title should be used
   * @param message
   *            the message to show in this dialog, or <code>null</code> to
   *            indicate that the error's message should be shown as the
   *            primary message
   * @param status
   *            the error to show to the user
   * @param displayMask
   *            the mask to use to filter the displaying of child items, as per
   *            <code>Status.matches</code>
   * @return the code of the button that was pressed that resulted in this
   *         dialog closing. This will be <code>Dialog.OK</code> if the OK
   *         button was pressed, or <code>Dialog.CANCEL</code> if this
   *         dialog's close window decoration or the ESC key was used.
   */
  public static int openError(
    Shell parentShell,
    String title,
    String message,
    IStatus status,
    int displayMask)
  {
    ErrorDialog dialog =
      new ErrorDialog(parentShell, title, message, status, displayMask);
    return dialog.open();
  }

  public static int openInfo(
    Shell parentShell,
    String title,
    String message,
    IStatus status,
    int displayMask)
  {
    InfoDialog dialog =
      new InfoDialog(parentShell, title, message, status, displayMask);
    return dialog.open();
  }

  public static int openWarning(
    Shell parentShell,
    String title,
    String message,
    IStatus status,
    int displayMask)
  {
    WarningDialog dialog =
      new WarningDialog(parentShell, title, message, status, displayMask);
    return dialog.open();
  }

  public static int openOptions(
    Shell parentShell,
    String title,
    String message,
    IStatus status,
    int displayMask,
    Choice[] options)
  {
    OptionsDialog dialog =
      new OptionsDialog(
        parentShell,
        title,
        message,
        status,
        displayMask,
        options);
    dialog.open();
    return dialog.getReturnCode();
  }

  /**
   * Populates the list using this error dialog's status object. This walks the
   * child stati of the status object and displays them in a list. The format
   * for each entry is status_path : status_message If the status's path was
   * null then it (and the colon) are omitted.
   */
  private void populateList(List list)
  {
    Iterator enumeration = statusList.iterator();
    while (enumeration.hasNext())
    {
      IStatus childStatus = (IStatus) enumeration.next();
      populateList(list, childStatus, 0);
    }
  }
  private void populateList(List list, IStatus status, int nesting)
  {
    if (!status.matches(displayMask))
    {
      return;
    }
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < nesting; i++)
    {
      sb.append("  ");
    }
    sb.append(status.getMessage());
    list.add(sb.toString());
    IStatus[] children = status.getChildren();
    for (int i = 0; i < children.length; i++)
    {
      populateList(list, children[i], nesting + 1);
    }
  }
  private void populateDetails(Text text, IStatus status, int nesting)
  {
    if (!status.matches(displayMask))
    {
      return;
    }
        
    String    tabChars    = StringUtils.repeat( ' ', nesting * 2 );
    String    messageLine = tabChars + status.getMessage() + System.getProperty("line.separator");
    Throwable except      = status.getException();
    
    text.append( messageLine );
    
    if( except != null )
    {
      String[] trace = StringUtils.getStackTrace( except );
      
      for( int index = 0; index < trace.length; index++ )
      {
        text.append( tabChars + "    " + trace[index] + System.getProperty("line.separator") );
      }
    }
    
    IStatus[] children = status.getChildren();
    for (int i = 0; i < children.length; i++)
    {
      populateDetails(text, children[i], nesting + 1);
    }
  }
  /**
   * Returns whether the given status object should be displayed.
   * 
   * @param status
   *            a status object
   * @param mask
   *            a mask as per <code>Status.matches</code>
   * @return <code>true</code> if the given status should be displayed, and
   *         <code>false</code> otherwise
   */
  protected static boolean shouldDisplay(IStatus status, int mask)
  {
    IStatus[] children = status.getChildren();
    if (children == null || children.length == 0)
    {
      return status.matches(mask);
    }
    for (int i = 0; i < children.length; i++)
    {
      if (children[i].matches(mask))
        return true;
    }
    return false;
  }
  /**
   * Toggles the unfolding of the details area. This is triggered by the user
   * pressing the details button.
   */
  private void toggleDetailsArea()
  {
    Point windowSize = getShell().getSize();
    int   newHeight  = -1;
    
    if (detailsCreated)
    {
      details.dispose();
      detailsCreated = false;
      detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
      
      // Without the following computeSize call the setSize call below throws an array out of bounds exception.
      // Very weird.
      getContents().computeSize(SWT.DEFAULT, SWT.DEFAULT);
      
      newHeight = savedSize.y;
    }
    else
    {
      if( savedSize == null ) savedSize = windowSize;
        
      details = createDropDownDetails((Composite) getContents());
      detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
      newHeight = getContents().computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
      newHeight = newHeight < 250 ? 250 : newHeight;
    }

    newHeight = newHeight > 400 ? 400 : newHeight;
    
    getShell().setSize( new Point(windowSize.x, newHeight) );
    parent.layout();
  }
}
