/*
 * 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 jdbc;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.rowset.spi.SyncProviderException;
import javax.swing.KeyStroke;

import ilog.views.gantt.IlvHierarchyChart;
import ilog.views.gantt.action.IlvAction;
import ilog.views.gantt.model.table.IlvTableGanttModel;
import ilog.views.util.data.IlvRowSetTableModel;
import ilog.views.util.swing.IlvSwingUtil;

/**
 * This class groups a number of IlvAction(s) that can be used when connecting a
 * Gantt model to a database.
 */
public class JdbcGanttActions {
  /**
   * An action that commits the current data model to the database
   */
  public static class CommitAction extends IlvAction {
    // The GanttChart or the ScheduleChart
    private IlvHierarchyChart gantt;

    public CommitAction(JdbcGanttExample sample) {
      super("Commit", null, KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK), "Commit Gantt Model",
          "Commit Gantt Model Modifications to the Database");
      setIcon(this.getClass(), "images/commit.png");
      setEnabled(!sample.tryConnectionFailed);
      this.gantt = sample.getChart();
    }

    /**
     * This method is called when the user wants to commit changes to the
     * database.
     */
    Override
    public void actionPerformed(ActionEvent event) {
      IlvTableGanttModel ganttModel = (IlvTableGanttModel) gantt.getGanttModel();
      IlvRowSetTableModel model = (IlvRowSetTableModel) ganttModel.getActivitiesTableModel();
      try {
        model.commit();
      } catch (SyncProviderException e) {
        IlvSwingUtil.showErrorDialog(null,
            "A conflict happened when synchronizing,\n" + "please rollback your modifcations", e);
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
      model = (IlvRowSetTableModel) ganttModel.getConstraintsTableModel();
      try {
        model.commit();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
    }
  }

  /**
   * An action that rollbacks the current modification of the data model
   */
  public static class RollbackAction extends IlvAction {
    // The GanttChart or the ScheduleChart
    private IlvHierarchyChart gantt;

    public RollbackAction(JdbcGanttExample sample) {
      super("Rollback", null, KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK), "Rollback Gantt Model",
          "Rollback Gantt Model Modifications");
      setIcon(this.getClass(), "images/rollback.png");
      setEnabled(!sample.tryConnectionFailed);
      this.gantt = sample.getChart();
    }

    /**
     * This method is called when the user wants to rollback current
     * modifications.
     */
    Override
    public void actionPerformed(ActionEvent event) {
      IlvTableGanttModel ganttModel = (IlvTableGanttModel) gantt.getGanttModel();
      IlvRowSetTableModel model = (IlvRowSetTableModel) ganttModel.getActivitiesTableModel();
      try {
        model.rollback();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
      model = (IlvRowSetTableModel) ganttModel.getConstraintsTableModel();
      try {
        model.rollback();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
    }
  }

  /**
   * An action that refresh the current data model with the database content
   */
  public static class RefreshAction extends IlvAction {
    // The GanttChart or the ScheduleChart
    private IlvHierarchyChart gantt;

    public RefreshAction(JdbcGanttExample sample) {
      super("Refresh Data", null, KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK), "Refresh Gantt Model",
          "Refresh Gantt Model from the Database");
      setIcon(this.getClass(), "images/refresh.png");
      setEnabled(!sample.tryConnectionFailed);
      this.gantt = sample.getChart();
    }

    /**
     * This method is called when the user wants to refresh gantt model with
     * database content.
     */
    Override
    public void actionPerformed(ActionEvent event) {
      IlvTableGanttModel ganttModel = (IlvTableGanttModel) gantt.getGanttModel();
      IlvRowSetTableModel model = (IlvRowSetTableModel) ganttModel.getActivitiesTableModel();
      try {
        model.refreshRows();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
      model = (IlvRowSetTableModel) ganttModel.getConstraintsTableModel();
      try {
        model.refreshRows();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
      model = (IlvRowSetTableModel) ganttModel.getReservationsTableModel();
      try {
        model.refreshRows();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
      model = (IlvRowSetTableModel) ganttModel.getResourcesTableModel();
      try {
        model.refreshRows();
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
    }
  }

  /**
   * An action that reinitialiazes the database tables
   */
  public static class ReInitAction extends IlvAction {
    private JdbcGanttExample sample;

    public ReInitAction(JdbcGanttExample sample) {
      super("Reinitialize Database", null, KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_DOWN_MASK),
          "Reinitialize Database Content", "Reinitialize Database Content with Initial Data");
      setIcon(this.getClass(), "images/reinit.png");
      setEnabled(!sample.tryConnectionFailed);
      this.sample = sample;
    }

    /**
     * This method is called when the user wants to reinitialize the database
     * tables with JViews Gantt distribution initial content.
     */
    Override
    public void actionPerformed(ActionEvent event) {
      try {
        Connection con = DriverManager.getConnection(JdbcGanttExample.databaseURL, JdbcGanttExample.user,
            JdbcGanttExample.passwd);
        InputStream stream = this.getClass().getResourceAsStream("script.sql");
        BufferedReader breader = new BufferedReader(new InputStreamReader(stream));
        Statement statement = con.createStatement();
        while (breader.ready()) {
          statement.executeUpdate(breader.readLine());
        }
        stream.close();
        con.close();
        // refresh the gantt model with the new database content
        sample.refreshAction.actionPerformed(null);
      } catch (SQLException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      } catch (IOException e) {
        IlvSwingUtil.showErrorDialog(null, e);
      }
    }
  }

  /**
   * An action that reinitialiazes the database tables
   */
  public static class ReConnectAction extends IlvAction {
    private JdbcGanttExample sample;

    public ReConnectAction(JdbcGanttExample sample) {
      super("Reconnect to the Database", null, KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK),
          "Reconnect to the Database", "Tries to reconnect to the Database");
      setIcon(this.getClass(), "images/reconnect.png");
      setEnabled(sample.tryConnectionFailed);
      this.sample = sample;
    }

    /**
     * This method is called when the user wants to reinitialize the database
     * tables with JViews Gantt distribution initial content.
     */
    Override
    public void actionPerformed(ActionEvent event) {
      sample.retryConnection();
    }
  }
}