/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */
package database;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

import ilog.views.gantt.IlvGanttModel;
import ilog.views.gantt.IlvHierarchyNode;
import ilog.views.gantt.IlvScheduleChart;
import ilog.views.gantt.action.IlvZoomToFitAction;
import ilog.views.gantt.swing.IlvJTable;
import shared.GanttCommand;
import shared.swing.ExampleFrame;
import xml.XMLGanttActions;
import xml.XMLScheduleExample;

/**
 * This example illustrates the design of a Gantt data model that communicates
 * with a back-end relational database. When a data model is loaded from an XML
 * file, the data model is not directly attached to the chart. Instead, the data
 * model is parsed into a simulated read-only relational database. This is an
 * instance of the <code>GanttModelDBROWrapper</code> class, which implements
 * the <code>GanttDBRO</code> interface. The simulated database is then
 * connected to an instance of <code>DBROGanttModel</code>, which is set as the
 * actual data model of the chart.
 */
public class DBScheduleExample extends XMLScheduleExample {

  /**
   * The logger for DBROGanttModel.
   */
  private Logger dbModelLogger;

  /**
   * The logger for GanttModelDBROWrapper.
   */
  private Logger modelDBWrapperLogger;

  /**
   * Constructs a new <code>DBScheduleExample</code>.
   */
  public DBScheduleExample() {
    dbModelLogger = Logger.getLogger(DBROGanttModel.logID);
    dbModelLogger.setLevel(Level.OFF);
    modelDBWrapperLogger = Logger.getLogger(GanttModelDBROWrapper.logID);
    modelDBWrapperLogger.setLevel(Level.OFF);
  }

  /**
   * Creates and returns the Gantt data model.
   */
  Override
  protected IlvGanttModel createGanttModel() {
    // Enable reservation caching in the schedule chart before the data model
    // is bound to it.
    ((IlvScheduleChart) getChart()).setReservationCachingEnabled(true);

    IlvGanttModel model = super.createGanttModel();
    return DBGanttActions.createDBGanttModel(model);
  }

  /**
   * Initially expand only the first parent resource. This allows the user to
   * see the load-on-demand capabilities when they manually expand the
   * additional rows.
   */
  Override
  public void initExpandedRows() {
    // Expand some rows so their children are visible.
    IlvHierarchyNode root = chart.getRootRow();
    IlvGanttModel model = getGanttModel();
    if (model != null && root != null) {
      if (model.getChildCount(root) > 0) {
        chart.expandAllRows(model.getChild(root, 0));
      }
    }
  }

  /**
   * Customizes the appearance of the Schedule chart.
   */
  Override
  protected void customizeChart() {
    super.customizeChart();

    // Make all of the columns in the table uneditable by removing their cell
    // editors.
    IlvJTable table = getChart().getTable();
    for (int i = 0; i < table.getColumnCount(); i++) {
      table.getColumn(i).setCellEditor(null);
    }
  }

  /**
   * Creates and installs the menu bar.
   */
  Override
  public JMenuBar createMenuBar() {
    JMenuBar menu = super.createMenuBar();
    // Remove the Edit menu.
    menu.remove(1);
    return menu;
  }

  /**
   * Populates the toolbar.
   */
  Override
  protected void populateToolBar(JToolBar toolbar) {
    addAction(toolbar, newAction);
    if (openAction != null) {
      addAction(toolbar, openAction);
    }
    if (saveAsAction != null) {
      addAction(toolbar, saveAsAction);
    }
    toolbar.addSeparator();
    addAction(toolbar, rowExpandCollapseAction);
    toolbar.addSeparator();
    addAction(toolbar, getChart().getZoomOutAction());
    addAction(toolbar, getChart().getZoomInAction());
    zoomToFitAction = new IlvZoomToFitAction(getChart(), "Zoom To Fit",
        KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK), "Zoom To Fit",
        "Zooms the time scale to fit the data.");
    addAction(toolbar, zoomToFitAction);
  }

  /**
   * Creates the File menu.
   */
  Override
  public JMenu createFileMenu() {
    JMenu menu = new JMenu("File");
    menu.setMnemonic(KeyEvent.VK_F);
    setStatusText(menu, "File operations");

    // Menu item for "New".
    newAction = new GanttCommand.NewDataModelAction(getChart());
    addAction(menu, newAction);

    if (isLocalFileAccessAllowed()) {
      // Menu item for "Open ...".
      openAction = new DBGanttActions.OpenXMLAsDatabaseAction(getChart());
      addAction(menu, openAction);

      // Menu item for "Save ...".
      saveAsAction = new XMLGanttActions.SaveAsXMLAction(getChart());
      addAction(menu, saveAsAction);
    }

    menu.addSeparator();

    // Menu item for "Reservation Caching".
    final JCheckBoxMenuItem reservationCachingItem = new JCheckBoxMenuItem("Reservation Caching");
    reservationCachingItem.setSelected(((IlvScheduleChart) getChart()).isReservationCachingEnabled());
    menu.add(reservationCachingItem);
    reservationCachingItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        ((IlvScheduleChart) getChart()).setReservationCachingEnabled(reservationCachingItem.isSelected());
      }
    });
    setStatusText(reservationCachingItem, "Toggles reservation caching.");

    menu.addSeparator();

    // Menu item for "Log Database Queries".
    final JCheckBoxMenuItem logDatabaseQueriesItem = new JCheckBoxMenuItem("Display Database Queries");
    logDatabaseQueriesItem.setSelected(modelDBWrapperLogger.getLevel() != Level.OFF);
    menu.add(logDatabaseQueriesItem);
    logDatabaseQueriesItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        if (logDatabaseQueriesItem.isSelected()) {
          modelDBWrapperLogger.setLevel(Level.INFO);
        } else {
          modelDBWrapperLogger.setLevel(Level.OFF);
        }
      }
    });
    setStatusText(logDatabaseQueriesItem, "Toggles display of queries to the Gantt database.");

    // Menu item for "Log Data Model Entities".
    final JCheckBoxMenuItem logDataModelItem = new JCheckBoxMenuItem("Display Data Model");
    logDataModelItem.setSelected(dbModelLogger.getLevel() != Level.OFF);
    menu.add(logDataModelItem);
    logDataModelItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        if (logDataModelItem.isSelected()) {
          dbModelLogger.setLevel(Level.INFO);
        } else {
          dbModelLogger.setLevel(Level.OFF);
        }
      }
    });
    setStatusText(logDataModelItem, "Toggles display of activity, resource, constraint, and reservation creation.");

    // Menu item for "Exit".
    if (isExitAllowed()) {
      menu.addSeparator();
      addAction(menu, exitAction);
    }

    return menu;
  }

  /**
   * Returns the title of the example.
   *
   * @return The title of the example.
   */
  Override
  public String getTitle() {
    return "Database and Load-On-Demand Schedule Chart Example";
  }

  /**
   * Application mainline.
   *
   * @param args
   *          The command line arguments.
   */
  public static void main(String[] args) {
    ExampleFrame.createAndShowGUI(DBScheduleExample.class);
  }

}