/*
 * LedgerComponent.java
 *
 * Status: Functional
 */

package gui;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;

import finance.*;
import gui.dialog.AccountDialog;

/**
 * The user interface component for {@link Ledger Ledger}s.
 */
public final class LedgerComponent extends JPanel
 {
  private static class DblClickHandler extends MouseAdapter
   {
    JTree tree;

    DblClickHandler(JTree tree)
     { this.tree = tree; }

    public void mousePressed(MouseEvent e)
     {
      if(e.getClickCount() < 2)
        return;
      TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
      if(selPath != null)
       {
        Object node = selPath.getLastPathComponent();
        if(node instanceof Ledger.AccountNode)
          Main.instance.displayAccount(((Ledger.AccountNode)node).getData());
       }
     }
   }

  private class SelectionHandler implements TreeSelectionListener
   {
    public void valueChanged(TreeSelectionEvent e)
     {
      TreePath selPath = tree.getSelectionPath();
      boolean editState = false;
      boolean deleteState = false;

      buttonDelete.setText("Delete Account");

      if(selPath != null)
       {
        Object node = selPath.getLastPathComponent();
        if(node instanceof Ledger.AccountNode)
         {
          Account account = ((Ledger.AccountNode)node).getData();
          editState = true;
          if(account.getEntries().size() == 0)
            deleteState = true;
         }
        else if(node instanceof Ledger.AccountTypeNode)
         {
          AccountType type = ((Ledger.AccountTypeNode)node).getData();
          deleteState = true;

          for(AccountType i : AccountType.getList())
            if(i.getName().equals(type.getName()))
             {
              deleteState = false;
              //break;
             }

          for(Account a : ledger.getAccounts())
            if(a.getType() == type)
             {
              deleteState = false;
              break;
             }

          if(deleteState)
            buttonDelete.setText("Delete Account Type");
         }
       }

      buttonEdit.setEnabled(editState);
      buttonDelete.setEnabled(deleteState);
     }
   }

  private class ButtonHandler
   {
    /**
     * Adds a new account.  This is the {@link ActionListener ActionListener}
     * method for the "Add Account" button.
     */
    public void button_AddAccount_Handler(ActionEvent event)
     {
      TreePath selPath = tree.getSelectionPath();
      if(selPath != null)
       {
        Object node = selPath.getLastPathComponent();
        if(node instanceof Ledger.AccountTypeNode)
          AccountDialog.showAdd(((Ledger.AccountTypeNode)node).getData());
        else if(node instanceof Ledger.AccountNode)
          AccountDialog.showAdd(((Ledger.AccountNode)node).getData().getType());
        else
          AccountDialog.showAdd();
       }
      else
        AccountDialog.showAdd();
     }


    /**
     * Edits the selected account.  This is the {@link ActionListener
     * ActionListener} method for the "Edit Account" button.
     */
    public void button_EditAccount_Handler(ActionEvent event)
     {
      TreePath selPath = tree.getSelectionPath();
      if(selPath != null)
       {
        Object node = selPath.getLastPathComponent();
        if(node instanceof Ledger.AccountNode)
          AccountDialog.showEdit(((Ledger.AccountNode)node).getData());
       }
     }


    /**
     * Deletes the selected account, after prompting the user.  This is the
     * {@link ActionListener ActionListener} method for the "Delete Account"
     * button.
     */
    public void button_DeleteAccount_Handler(ActionEvent event)
     {
      TreePath selPath = tree.getSelectionPath();
      if(selPath == null)
        return;

      Object node = selPath.getLastPathComponent();
      if(node instanceof Ledger.AccountNode)
       {
        Account account = ((Ledger.AccountNode)node).getData();
        String msg = "Are you sure you want to delete the selected account?";
        if(JOptionPane.showConfirmDialog(Main.instance, msg, "Confirm Delete", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION)
          Main.getDB().removeAccount(account);
       }
      else if(node instanceof Ledger.AccountTypeNode)
       {
        AccountType type = ((Ledger.AccountTypeNode)node).getData();
        String msg = "Are you sure you want to delete the selected account type?";
        if(JOptionPane.showConfirmDialog(Main.instance, msg, "Confirm Delete", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION)
          Main.getDB().removeAccountType(type);
       }
     }
   }


  Ledger ledger = null;
  JTree tree = null;

  private JButton buttonAdd = new JButton("Add Account");
  private JButton buttonEdit = new JButton("Edit Account");
  private JButton buttonDelete = new JButton("Delete Account");


  /**
   * Constructs a new {@code LedgerComponent}.
   */
  public LedgerComponent(Ledger ledger)
   {
    this.ledger = ledger;

    setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

    tree = new JTree(ledger.getDataModel());

    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.addTreeSelectionListener(new SelectionHandler());
    tree.addMouseListener(new DblClickHandler(tree));
    tree.setRootVisible(false);

    c.fill = GridBagConstraints.BOTH;
    c.anchor = GridBagConstraints.NORTHWEST;
    c.weightx = 1;
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.weighty = 1;
    add(new JScrollPane(tree), c);

    c.gridwidth = 1;
    c.weighty = 0;

    ButtonHandler buttonHandler = new ButtonHandler();
    buttonAdd.addActionListener(new ActionHandler(buttonHandler, "button_AddAccount_Handler"));
    add(buttonAdd, c);

    buttonEdit.addActionListener(new ActionHandler(buttonHandler, "button_EditAccount_Handler"));
    buttonEdit.setEnabled(false);
    add(buttonEdit, c);

    c.gridwidth = GridBagConstraints.REMAINDER;

    buttonDelete.addActionListener(new ActionHandler(buttonHandler, "button_DeleteAccount_Handler"));
    buttonDelete.setEnabled(false);
    add(buttonDelete, c);
   }
 }
