content: package library.assistant.ui.main;
  
  import com.jfoenix.controls.JFXButton;
  import com.jfoenix.controls.JFXDrawer;
  import com.jfoenix.controls.JFXHamburger;
  import com.jfoenix.controls.JFXTabPane;
  import com.jfoenix.controls.JFXTextField;
  import com.jfoenix.transitions.hamburger.HamburgerSlideCloseTransition;
  import java.io.IOException;
  import java.net.URL;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Timestamp;
  import java.util.Arrays;
  import java.util.Date;
  import java.util.ResourceBundle;
  import java.util.concurrent.TimeUnit;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javafx.collections.FXCollections;
  import javafx.collections.ObservableList;
  import javafx.event.ActionEvent;
  import javafx.event.Event;
  import javafx.fxml.FXML;
  import javafx.fxml.FXMLLoader;
  import javafx.fxml.Initializable;
  import javafx.scene.Scene;
  import javafx.scene.chart.PieChart;
  import javafx.scene.control.Tab;
  import javafx.scene.control.TextField;
  import javafx.scene.input.KeyCode;
  import javafx.scene.input.KeyEvent;
  import javafx.scene.input.MouseEvent;
  import javafx.scene.layout.AnchorPane;
  import javafx.scene.layout.HBox;
  import javafx.scene.layout.StackPane;
  import javafx.scene.layout.VBox;
  import javafx.scene.text.Text;
  import javafx.stage.Stage;
  import library.assistant.alert.AlertMaker;
  import library.assistant.database.DataHelper;
  import library.assistant.database.DatabaseHandler;
  import library.assistant.ui.callback.BookReturnCallback;
  import library.assistant.ui.issuedlist.IssuedListController;
  import library.assistant.ui.main.toolbar.ToolbarController;
  import library.assistant.util.LibraryAssistantUtil;
  
  public class MainController implements Initializable, BookReturnCallback {
  
      private static final String BOOK_NOT_AVAILABLE = "Not Available";
      private static final String NO_SUCH_BOOK_AVAILABLE = "No Such Book Available";
      private static final String NO_SUCH_MEMBER_AVAILABLE = "No Such Member Available";
      private static final String BOOK_AVAILABLE = "Available";
  
      private Boolean isReadyForSubmission = false;
      private DatabaseHandler databaseHandler;
      private PieChart bookChart;
      private PieChart memberChart;
  
      @FXML
      private HBox book_info;
      @FXML
      private HBox member_info;
      @FXML
      private TextField bookIDInput;
      @FXML
      private Text bookName;
      @FXML
      private Text bookAuthor;
      @FXML
      private Text bookStatus;
      @FXML
      private TextField memberIDInput;
      @FXML
      private Text memberName;
      @FXML
      private Text memberMobile;
      @FXML
      private JFXTextField bookID;
      @FXML
      private StackPane rootPane;
      @FXML
      private JFXHamburger hamburger;
      @FXML
      private JFXDrawer drawer;
      @FXML
      private Text memberNameHolder;
      @FXML
      private Text memberEmailHolder;
      @FXML
      private Text memberContactHolder;
      @FXML
      private Text bookNameHolder;
      @FXML
      private Text bookAuthorHolder;
      @FXML
      private Text bookPublisherHolder;
      @FXML
      private Text issueDateHolder;
      @FXML
      private Text numberDaysHolder;
      @FXML
      private Text fineInfoHolder;
      @FXML
      private AnchorPane rootAnchorPane;
      @FXML
      private JFXButton renewButton;
      @FXML
      private JFXButton submissionButton;
      @FXML
      private HBox submissionDataContainer;
      @FXML
      private StackPane bookInfoContainer;
      @FXML
      private StackPane memberInfoContainer;
      @FXML
      private Tab bookIssueTab;
      @FXML
      private Tab renewTab;
      @FXML
      private JFXTabPane mainTabPane;
      @FXML
      private JFXButton btnIssue;
  
      @Override
      public void initialize(URL url, ResourceBundle rb) {
          databaseHandler = DatabaseHandler.getInstance();
  
          initDrawer();
          initGraphs();
          initComponents();
      }
  
      @FXML
      private void loadBookInfo(ActionEvent event) {
          clearBookCache();
          enableDisableGraph(false);
  
          String id = bookIDInput.getText();
          ResultSet rs = DataHelper.getBookInfoWithIssueData(id);
          Boolean flag = false;
          try {
              if (rs.next()) {
                  String bName = rs.getString("title");
                  String bAuthor = rs.getString("author");
                  Boolean bStatus = rs.getBoolean("isAvail");
                  Timestamp issuedOn = rs.getTimestamp("issueTime");
  
                  bookName.setText(bName);
                  bookAuthor.setText(bAuthor);
                  String status = (bStatus) ? BOOK_AVAILABLE : String.format("Issued on %s", LibraryAssistantUtil.getDateString(new Date(issuedOn.getTime())));
                  if (!bStatus) {
                      bookStatus.getStyleClass().add("not-available");
                  } else {
                      bookStatus.getStyleClass().remove("not-available");
                  }
                  bookStatus.setText(status);
  
                  flag = true;
              }
  
              if (!flag) {
                  bookName.setText(NO_SUCH_BOOK_AVAILABLE);
              } else {
                  memberIDInput.requestFocus();
              }
  
          } catch (SQLException ex) {
              Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, ex);
          }
      }
  
      void clearBookCache() {
          bookName.setText("");
          bookAuthor.setText("");
          bookStatus.setText("");
      }
  
      void clearMemberCache() {
          memberName.setText("");
          memberMobile.setText("");
      }
  
      @FXML
      private void loadMemberInfo(ActionEvent event) {
          clearMemberCache();
          enableDisableGraph(false);
  
          String id = memberIDInput.getText();
          String qu = "SELECT * FROM MEMBER WHERE id = '" + id + "'";
          ResultSet rs = databaseHandler.execQuery(qu);
          Boolean flag = false;
          try {
              while (rs.next()) {
                  String mName = rs.getString("name");
                  String mMobile = rs.getString("mobile");
  
                  memberName.setText(mName);
                  memberMobile.setText(mMobile);
  
                  flag = true;
              }
  
              if (!flag) {
                  memberName.setText(NO_SUCH_MEMBER_AVAILABLE);
              } else {
                  btnIssue.requestFocus();
              }
          } catch (SQLException ex) {
              Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, ex);
          }
      }
  
      @FXML
      private void loadIssueOperation(ActionEvent event) {
          if (checkForIssueValidity()) {
              JFXButton btn = new JFXButton("Okay!");
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Invalid Input", null);
              return;
          }
          if (bookStatus.getText().equals(BOOK_NOT_AVAILABLE)) {
              JFXButton btn = new JFXButton("Okay!");
              JFXButton viewDetails = new JFXButton("View Details");
              viewDetails.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
                  String bookToBeLoaded = bookIDInput.getText();
                  bookID.setText(bookToBeLoaded);
                  bookID.fireEvent(new ActionEvent());
                  mainTabPane.getSelectionModel().select(renewTab);
              });
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn, viewDetails), "Already issued book", "This book is already issued. Cant process issue request");
              return;
          }
  
          String memberID = memberIDInput.getText();
          String bookID = bookIDInput.getText();
  
          JFXButton yesButton = new JFXButton("YES");
          yesButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event1) -> {
              String str = "INSERT INTO ISSUE(memberID,bookID) VALUES ("
                      + "'" + memberID + "',"
                      + "'" + bookID + "')";
              String str2 = "UPDATE BOOK SET isAvail = false WHERE id = '" + bookID + "'";
              System.out.println(str + " and " + str2);
  
              if (databaseHandler.execAction(str) && databaseHandler.execAction(str2)) {
                  JFXButton button = new JFXButton("Done!");
                  button.setOnAction((actionEvent) -> {
                      bookIDInput.requestFocus();
                  });
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(button), "Book Issue Complete", null);
                  refreshGraphs();
              } else {
                  JFXButton button = new JFXButton("Okay.I'll Check");
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(button), "Issue Operation Failed", null);
              }
              clearIssueEntries();
          });
          JFXButton noButton = new JFXButton("NO");
          noButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event1) -> {
              JFXButton button = new JFXButton("That's Okay");
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(button), "Issue Cancelled", null);
              clearIssueEntries();
          });
          AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(yesButton, noButton), "Confirm Issue",
                  String.format("Are you sure want to issue the book '%s' to '%s' ?", bookName.getText(), memberName.getText()));
      }
  
      @FXML
      private void loadBookInfo2(ActionEvent event) {
          clearEntries();
          ObservableList<String> issueData = FXCollections.observableArrayList();
          isReadyForSubmission = false;
  
          try {
              String id = bookID.getText();
              String myQuery = "SELECT ISSUE.bookID, ISSUE.memberID, ISSUE.issueTime, ISSUE.renew_count,\n"
                      + "MEMBER.name, MEMBER.mobile, MEMBER.email,\n"
                      + "BOOK.title, BOOK.author, BOOK.publisher\n"
                      + "FROM ISSUE\n"
                      + "LEFT JOIN MEMBER\n"
                      + "ON ISSUE.memberID=MEMBER.ID\n"
                      + "LEFT JOIN BOOK\n"
                      + "ON ISSUE.bookID=BOOK.ID\n"
                      + "WHERE ISSUE.bookID='" + id + "'";
              ResultSet rs = databaseHandler.execQuery(myQuery);
              if (rs.next()) {
                  memberNameHolder.setText(rs.getString("name"));
                  memberContactHolder.setText(rs.getString("mobile"));
                  memberEmailHolder.setText(rs.getString("email"));
  
                  bookNameHolder.setText(rs.getString("title"));
                  bookAuthorHolder.setText(rs.getString("author"));
                  bookPublisherHolder.setText(rs.getString("publisher"));
  
                  Timestamp mIssueTime = rs.getTimestamp("issueTime");
                  Date dateOfIssue = new Date(mIssueTime.getTime());
                  issueDateHolder.setText(LibraryAssistantUtil.formatDateTimeString(dateOfIssue));
                  Long timeElapsed = System.currentTimeMillis() - mIssueTime.getTime();
                  Long days = TimeUnit.DAYS.convert(timeElapsed, TimeUnit.MILLISECONDS) + 1;
                  String daysElapsed = String.format("Used %d days", days);
                  numberDaysHolder.setText(daysElapsed);
                  Float fine = LibraryAssistantUtil.getFineAmount(days.intValue());
                  if (fine > 0) {
                      fineInfoHolder.setText(String.format("Fine : %.2f", LibraryAssistantUtil.getFineAmount(days.intValue())));
                  } else {
                      fineInfoHolder.setText("");
                  }
  
                  isReadyForSubmission = true;
                  disableEnableControls(true);
                  submissionDataContainer.setOpacity(1);
              } else {
                  JFXButton button = new JFXButton("Okay.I'll Check");
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(button), "No such Book Exists in Issue Database", null);
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
  
      }
  
      @FXML
      private void loadSubmissionOp(ActionEvent event) {
          if (!isReadyForSubmission) {
              JFXButton btn = new JFXButton("Okay!");
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Please select a book to submit", "Cant simply submit a null book :-)");
              return;
          }
  
          JFXButton yesButton = new JFXButton("YES, Please");
          yesButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent ev) -> {
              String id = bookID.getText();
              String ac1 = "DELETE FROM ISSUE WHERE BOOKID = '" + id + "'";
              String ac2 = "UPDATE BOOK SET ISAVAIL = TRUE WHERE ID = '" + id + "'";
  
              if (databaseHandler.execAction(ac1) && databaseHandler.execAction(ac2)) {
                  JFXButton btn = new JFXButton("Done!");
                  btn.setOnAction((actionEvent) -> {
                      bookID.requestFocus();
                  });
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Book has been submitted", null);
                  disableEnableControls(false);
                  submissionDataContainer.setOpacity(0);
              } else {
                  JFXButton btn = new JFXButton("Okay.I'll Check");
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Submission Has Been Failed", null);
              }
          });
          JFXButton noButton = new JFXButton("No, Cancel");
          noButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent ev) -> {
              JFXButton btn = new JFXButton("Okay!");
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Submission Operation cancelled", null);
          });
  
          AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(yesButton, noButton), "Confirm Submission Operation", "Are you sure want to return the book ?");
      }
  
      @FXML
      private void loadRenewOp(ActionEvent event) {
          if (!isReadyForSubmission) {
              JFXButton btn = new JFXButton("Okay!");
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Please select a book to renew", null);
              return;
          }
          JFXButton yesButton = new JFXButton("YES, Please");
          yesButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event1) -> {
              String ac = "UPDATE ISSUE SET issueTime = CURRENT_TIMESTAMP, renew_count = renew_count+1 WHERE BOOKID = '" + bookID.getText() + "'";
              System.out.println(ac);
              if (databaseHandler.execAction(ac)) {
                  JFXButton btn = new JFXButton("Alright!");
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Book Has Been Renewed", null);
                  disableEnableControls(false);
                  submissionDataContainer.setOpacity(0);
              } else {
                  JFXButton btn = new JFXButton("Okay!");
                  AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Renew Has Been Failed", null);
              }
          });
          JFXButton noButton = new JFXButton("No, Don't!");
          noButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event1) -> {
              JFXButton btn = new JFXButton("Okay!");
              AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(btn), "Renew Operation cancelled", null);
          });
          AlertMaker.showMaterialDialog(rootPane, rootAnchorPane, Arrays.asList(yesButton, noButton), "Confirm Renew Operation", "Are you sure want to renew the book ?");
      }
  
      private Stage getStage() {
          return (Stage) rootPane.getScene().getWindow();
      }
  
      @FXML
      private void handleMenuClose(ActionEvent event) {
          getStage().close();
      }
  
      @FXML
      private void handleMenuAddBook(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/addbook/add_book.fxml"), "Add New Book", null);
      }
  
      @FXML
      private void handleMenuAddMember(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/addmember/member_add.fxml"), "Add New Member", null);
      }
  
      @FXML
      private void handleMenuViewBook(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/listbook/book_list.fxml"), "Book List", null);
      }
  
      @FXML
      private void handleAboutMenu(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/about/about.fxml"), "About Me", null);
      }
  
      @FXML
      private void handleMenuSettings(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/settings/settings.fxml"), "Settings", null);
      }
  
      @FXML
      private void handleMenuViewMemberList(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/listmember/member_list.fxml"), "Member List", null);
      }
  
      @FXML
      private void handleIssuedList(ActionEvent event) {
          Object controller = LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/issuedlist/issued_list.fxml"), "Issued Book List", null);
          if (controller != null) {
              IssuedListController cont = (IssuedListController) controller;
              cont.setBookReturnCallback(this);
          }
      }
  
      @FXML
      private void handleMenuFullScreen(ActionEvent event) {
          Stage stage = getStage();
          stage.setFullScreen(!stage.isFullScreen());
      }
  
      private void initDrawer() {
          try {
              FXMLLoader loader = new FXMLLoader(getClass().getResource("/library/assistant/ui/main/toolbar/toolbar.fxml"));
              VBox toolbar = loader.load();
              drawer.setSidePane(toolbar);
              ToolbarController controller = loader.getController();
              controller.setBookReturnCallback(this);
          } catch (IOException ex) {
              Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, ex);
          }
          HamburgerSlideCloseTransition task = new HamburgerSlideCloseTransition(hamburger);
          task.setRate(-1);
          hamburger.addEventHandler(MouseEvent.MOUSE_CLICKED, (Event event) -> {
              drawer.toggle();
          });
          drawer.setOnDrawerOpening((event) -> {
              task.setRate(task.getRate() * -1);
              task.play();
              drawer.toFront();
          });
          drawer.setOnDrawerClosed((event) -> {
              drawer.toBack();
              task.setRate(task.getRate() * -1);
              task.play();
          });
      }
  
      private void clearEntries() {
          memberNameHolder.setText("");
          memberEmailHolder.setText("");
          memberContactHolder.setText("");
  
          bookNameHolder.setText("");
          bookAuthorHolder.setText("");
          bookPublisherHolder.setText("");
  
          issueDateHolder.setText("");
          numberDaysHolder.setText("");
          fineInfoHolder.setText("");
  
          disableEnableControls(false);
          submissionDataContainer.setOpacity(0);
      }
  
      private void disableEnableControls(Boolean enableFlag) {
          if (enableFlag) {
              renewButton.setDisable(false);
              submissionButton.setDisable(false);
          } else {
              renewButton.setDisable(true);
              submissionButton.setDisable(true);
          }
      }
  
      private void clearIssueEntries() {
          bookIDInput.clear();
          memberIDInput.clear();
          bookName.setText("");
          bookAuthor.setText("");
          bookStatus.setText("");
          memberMobile.setText("");
          memberName.setText("");
          enableDisableGraph(true);
      }
  
      private void initGraphs() {
          bookChart = new PieChart(databaseHandler.getBookGraphStatistics());
          memberChart = new PieChart(databaseHandler.getMemberGraphStatistics());
          bookInfoContainer.getChildren().add(bookChart);
          memberInfoContainer.getChildren().add(memberChart);
  
          bookIssueTab.setOnSelectionChanged((Event event) -> {
              clearIssueEntries();
              if (bookIssueTab.isSelected()) {
                  refreshGraphs();
              }
          });
      }
  
      private void refreshGraphs() {
          bookChart.setData(databaseHandler.getBookGraphStatistics());
          memberChart.setData(databaseHandler.getMemberGraphStatistics());
      }
  
      private void enableDisableGraph(Boolean status) {
          if (status) {
              bookChart.setOpacity(1);
              memberChart.setOpacity(1);
          } else {
              bookChart.setOpacity(0);
              memberChart.setOpacity(0);
          }
      }
  
      private boolean checkForIssueValidity() {
          bookIDInput.fireEvent(new ActionEvent());
          memberIDInput.fireEvent(new ActionEvent());
          return bookIDInput.getText().isEmpty() || memberIDInput.getText().isEmpty()
                  || memberName.getText().isEmpty() || bookName.getText().isEmpty()
                  || bookName.getText().equals(NO_SUCH_BOOK_AVAILABLE) || memberName.getText().equals(NO_SUCH_MEMBER_AVAILABLE);
      }
  
      @Override
      public void loadBookReturn(String bookID) {
          this.bookID.setText(bookID);
          mainTabPane.getSelectionModel().select(renewTab);
          loadBookInfo2(null);
          getStage().toFront();
          if (drawer.isOpened()) {
              drawer.close();
          }
      }
  
      @FXML
      private void handleIssueButtonKeyPress(KeyEvent event) {
          if (event.getCode() == KeyCode.ENTER) {
              loadIssueOperation(null);
          }
      }
  
      private void initComponents() {
          mainTabPane.tabMinWidthProperty().bind(rootAnchorPane.widthProperty().divide(mainTabPane.getTabs().size()).subtract(15));
      }
  
      @FXML
      private void handleMenuOverdueNotification(ActionEvent event) {
          LibraryAssistantUtil.loadWindow(getClass().getResource("/library/assistant/ui/notifoverdue/overdue_notification.fxml"), "Notify Users", null);
      }
  
  }
  