/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
package gov.vha.edb.rules.web.builder;

import ilog.rules.repository.brm.IlrBrmConstants;
import ilog.rules.repository.brm.IlrBrmRule;
import ilog.rules.repository.brm.IlrProject;
import ilog.rules.repository.facility.IlrPersistenceHandler;
import ilog.rules.repository.facility.IlrPersistenceManager;
import ilog.rules.repository.model.*;
import ilog.webui.dhtml.IlxWPort;
import ilog.webui.dhtml.IlxWRequestDesc;

public class BuilderActions {

  // Repository actions.
  public static final String ACTION_NEWPROJECT = "newProject";
  public static final String ACTION_SAVEREPOSITORY = "saveRepository";
  public static final String ACTION_OPENPROJECT = "openProject";
  public static final String ACTION_EXIT = "exit";
  // View actions.
  public static final String ACTION_CHANGESKIN = "changeSkin";
  public static final String ACTION_PROPPLACEMENT = "propPlacement";
  // Project actions.
  public static final String ACTION_NEWPACKAGE = "newPackage";
  public static final String ACTION_NEWRULE = "newRule";
  public static final String ACTION_CHOOSENEWRULEMODEL = "chooseNewRuleModel";
  public static final String ACTION_DELETE = "delete";
  public static final String ACTION_CUT = "cut";
  public static final String ACTION_COPY = "copy";
  public static final String ACTION_PASTE = "paste";
  // Rule actions.
  public static final String ACTION_UNDO = "undo";
  public static final String ACTION_REDO = "redo";
  public static final String ACTION_CHECKRULE = "checkRule";
  // Help actions.
  public static final String ACTION_ABOUT = "about";

  public static WebAction.Map makeActionMap() {
    return new WebAction.Map();
  }

  public static class NewProjectAction extends WebAction {

    private static final long serialVersionUID = 2222869652812721932L;

    public NewProjectAction() {
      super(ACTION_NEWPROJECT);
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      IlrRefPackage refPack = builder.getCurrentExtent();
      IlrProject project = IlrProject.createProject(refPack);
      builder.setCurrentProject(project);
      port.addUpdatingRequest(IlxWRequestDesc.getDesc("/jsp/header.jsp",
                                                      "header"));
    }

  }

  public static class SaveRepositoryAction extends WebAction {

    private static final long serialVersionUID = 1878164905584836229L;

    public SaveRepositoryAction() {
      super(ACTION_SAVEREPOSITORY);
    }

    public boolean isEnabled(WebBuilder builder) {
      IlrRefPackage refPack = builder.getCurrentExtent();
      if (refPack == null) return false;
      boolean ret = refPack.isModified() || (builder.getEditedElement() != null ?
          builder.getEditedElement().isModified() : false);
      if (builder.getClientProperties().isModified() != ret) {
		  builder.getClientProperties().setModified(ret);
		  builder.getClientProperties().invalidate();
	  }
      return ret;
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      try {
        IlrRepository rep = builder.getCurrentRepository();
        IlrPersistenceManager pManager = rep.getPersistenceManager();
        IlrPersistenceHandler handler = rep.getPersistenceHandler();
        if (handler.isOldVersion()) {
          rep.getPersistenceManager().loadAll(false);
          handler.reset();
          handler.initialize();
          handler.open();
          rep.reset();
          rep.clearDeletedElements();
          rep.setPersistenceHandler(handler);
        }
        pManager.saveRepository();

        String msg = builder.getMessage("Messages.RepositorySaved");
        builder.addMessage(msg);
      } catch (IlrRepException ex) {
        System.err.println(ex);
      }
      builder.updateActionStates();
    }

  }

  public static class OpenProjectAction extends WebAction {

    private static final long serialVersionUID = 1742502766855841039L;
    private IlrProject project;

    public OpenProjectAction(String id, IlrProject project) {
      super(id,
            project.getName(),
            null);
      this.project = project;
    }

    public boolean isSelectable() {
      return true;
    }

    public boolean isSelected(WebBuilder builder) {
      return (this.project == builder.getCurrentProject());
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.setCurrentProject(this.project);
      port.addUpdatingRequest(IlxWRequestDesc.getDesc("/jsp/header.jsp",
                                                      "header"));
    }

  }

  public static class DeleteAction extends WebAction {

    private static final long serialVersionUID = -5358606082095409072L;

    public DeleteAction() {
      super(ACTION_DELETE,
            WebBuilder.getProperty(ACTION_DELETE + ".text"),
            "new Function(\"action\", \"confirmDelete(action)\")");
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      IlrElement element = builder.getEditedElement();
      if (element != null) {
        element.delete();
        builder.getExplorerPanel().getTree().clearSelection();
        builder.setEditedElement(null);
      }
    }

    public boolean isEnabled(WebBuilder builder) {
      IlrElement element = builder.getEditedElement();
      return (element != null && element.acceptsDelete());
    }

  }

  public static class CutAction extends WebAction {

    private static final long serialVersionUID = 5109875742113173696L;

    public CutAction() {
      super(ACTION_CUT);
    }

    public boolean isEnabled(WebBuilder builder) {
      IlrElement element = builder.getEditedElement();
      return (element != null
          && !(element instanceof IlrProject)
          && element.acceptsDelete());
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.cut();
    }

  }

  public static class CopyAction extends WebAction {

    private static final long serialVersionUID = -2047842812328689323L;

    public CopyAction() {
      super(ACTION_COPY);
    }

    public boolean isEnabled(WebBuilder builder) {
      IlrElement element = builder.getEditedElement();
      return (element != null
          && !(element instanceof IlrProject));
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.copy();
    }

  }

  public static class PasteAction extends WebAction {

    private static final long serialVersionUID = 6878416743804556141L;

    public PasteAction() {
      super(ACTION_PASTE);
    }

    public boolean isEnabled(WebBuilder builder) {
      IlrElement element = builder.getEditedElement();
      IlrPackage p = builder.getCurrentPackage();
      boolean packOk = (p != null && !p.isFrozen());
      return builder.canPaste()
          && packOk
          && element != null;
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.paste();
    }

  }

  public static class UndoAction extends WebAction {

    private static final long serialVersionUID = 7678124826415316890L;

    public UndoAction() {
      super(ACTION_UNDO);
    }

    public boolean isEnabled(WebBuilder builder) {
      return builder.getCenterPanel().canUndo();
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.getCenterPanel().undo();
    }

  }

  public static class RedoAction extends WebAction {

    private static final long serialVersionUID = -8940775555234120114L;

    public RedoAction() {
      super(ACTION_REDO);
    }

    public boolean isEnabled(WebBuilder builder) {
      return builder.getCenterPanel().canRedo();
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.getCenterPanel().redo();
    }

  }

  public static class CheckRuleAction extends WebAction {

    private static final long serialVersionUID = 7030273590310415492L;

    public CheckRuleAction() {
      super(ACTION_CHECKRULE);
    }

    public boolean isEnabled(WebBuilder builder) {
      return builder.getCenterPanel().canCheck();
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.getCenterPanel().check();
    }

  }

  public static class NewPackageAction extends WebAction {

    private static final long serialVersionUID = -8733646593694184684L;

    public NewPackageAction() {
      super(ACTION_NEWPACKAGE);
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      String newPackageName = (args.length > 0) ? args[0] : null;
      IlrRefPackage refPack = builder.getCurrentExtent();
      IlrRefClass refClass
          = refPack.findRefClass(IlrBrmConstants.RULE_PACKAGE_CLASS);
      IlrPackage pack = (IlrPackage) refClass.createInstance(newPackageName);
      IlrPackage curPack = builder.getCurrentPackage();
      IlrProject curPrj = builder.getCurrentProject();
      if (curPack != null && curPack.isInstanceOf((IlrElementClass) refClass.refMetaObject(), true)) {
        curPack.addContent(pack, true);
      }  else {
        pack.setName(pack.findNewName(pack.getElementClass().getName()));
        curPrj.addExplicitMember(pack);
      }
      builder.getExplorerPanel().setSelectedElement(pack);
    }

    public boolean isEnabled(WebBuilder builder) {
      IlrRefPackage refPack = builder.getCurrentExtent();
      IlrProject curProj = builder.getCurrentProject();
      IlrPackage curPack = builder.getCurrentPackage();
      IlrElementClass eltClass
          = refPack.getElementClass(IlrBrmConstants.RULE_PACKAGE_CLASS);
      if (curPack == null || !(curPack.isInstanceOf(eltClass, true)))
        return (curProj != null && !curProj.isFrozen());
      else
        return (curPack != null && !curPack.isFrozen());
    }

  }

  public static class NewRuleAction extends WebAction {

    private static final long serialVersionUID = -6690480728879991405L;

    public NewRuleAction() {
      super(ACTION_NEWRULE);
    }

    public boolean isEnabled(WebBuilder builder) {
      if (builder.getEditedElement() instanceof IlrProject) {
        return false;
      }
      IlrRefPackage refPack = builder.getCurrentExtent();
      IlrElementClass eltClass
          = refPack.getElementClass(IlrBrmConstants.RULE_PACKAGE_CLASS);
      IlrPackage p = builder.getCurrentPackage();
      return (p != null && !p.isFrozen() && (p.isInstanceOf(eltClass, true)));
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      IlrBrmRule rule = builder.getCurrentRuleTemplate();
      try {
        IlrBrmRule clone = (IlrBrmRule) rule.clone();
        IlrNamespace ns = null;
        ns = builder.getCurrentPackage();
        clone.setName(ns.findNewName(rule.getName()));
        ns.addContent(clone, true);
        builder.getExplorerPanel().setSelectedElement(clone);
      } catch (CloneNotSupportedException ex) {
      }
    }

  }


  public static class ChooseNewRuleModelAction extends WebAction {
    private static final long serialVersionUID = 889396068464912595L;

    public ChooseNewRuleModelAction() {
      super(ACTION_CHOOSENEWRULEMODEL);
    }

    public void invoke(IlxWPort port, String[] args) {
      throw new RuntimeException("should never be called");
    }

    public boolean isEnabled(WebBuilder builder) {
      if (builder.getEditedElement() instanceof IlrProject) {
        return false;
      } else {
        IlrRefPackage refPack = builder.getCurrentExtent();
        IlrElementClass eltClass
            = refPack.getElementClass(IlrBrmConstants.RULE_PACKAGE_CLASS);
        IlrPackage p = builder.getCurrentPackage();
        return (p != null && !p.isFrozen() && (p.isInstanceOf(eltClass, true)));
      }
    }

    public boolean isInvokable() {
      return false;
    }

  }

  public static class NewRuleFromModelAction extends WebAction {

    private static final long serialVersionUID = 5205510083436984866L;
    private IlrBrmRule rule;

    public NewRuleFromModelAction(String id, IlrBrmRule rule) {
      super(id, rule.getName(), null, null);
      this.rule = rule;
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      builder.setCurrentRuleTemplate(rule);
      try {
        IlrBrmRule clone = (IlrBrmRule) rule.clone();
        IlrNamespace ns = null;
        ns = builder.getCurrentPackage();
        clone.setName(ns.findNewName(rule.getName()));
        ns.addContent(clone, true);
        builder.getExplorerPanel().setSelectedElement(clone);
      } catch (CloneNotSupportedException ex) {
      }
    }

  }


  public static class PropertiesPlacementAction extends WebAction {

    private static final long serialVersionUID = 6696055021921338590L;
    private int mode;

    public PropertiesPlacementAction(String name,
                                     String displayName,
                                     String mode) {
      this(name, displayName, "center".equals(mode) ? WebBuilder.PROPERTIES_CENTER :
                              WebBuilder.PROPERTIES_EAST);
    }

    public PropertiesPlacementAction(String name,
                                     String displayName,
                                     int mode) {
      super(name,
            displayName,
            null, // No JS function.
            null); // No icon.
      this.mode = mode;
    }

    public void invoke(IlxWPort port, String[] args) {
      getBuilder(port).setPropertiesPlacement(mode);
    }

    public boolean isSelectable() {
      return true;
    }

    public boolean isSelected(WebBuilder builder) {
      int mode = builder.getPropertiesPlacement();
      return (this.mode == mode);
    }

  }

  public static class AboutAction extends WebAction {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1810201697699072055L;

	public AboutAction() {
      super(ACTION_ABOUT);
    }

    public void invoke(IlxWPort port, String[] args) {
    }

  }

  public static class ExitAction extends WebAction {

    private static final long serialVersionUID = 7272600862357067000L;

    public ExitAction() {
    	super(ACTION_EXIT,
              WebBuilder.getProperty(ACTION_EXIT + ".text"),
              "new Function(\"action\", \"confirmExit(action)\")");
    }

    public void invoke(IlxWPort port, String[] args) {
      WebBuilder builder = getBuilder(port);
      port.addUpdatingRequest(IlxWRequestDesc.getDesc(builder.exitPath,"_top"));
    }

  }

  public static class ChangeSkinAction extends WebAction {

    private static final long serialVersionUID = 1492426615129345237L;
    private String fileName;

    public ChangeSkinAction(String name,
                            String displayName) {
      this(name, displayName, "");
    }

    public ChangeSkinAction(String name,
                            String displayName,
                            String fileName) {
      super(name, displayName, null, null);
      this.fileName = fileName;
    }

    public void invoke(IlxWPort port, String[] args) {
      getBuilder(port).setSkin(port, fileName);
    }

    public boolean isSelectable() {
      return true;
    }

    public boolean isSelected(WebBuilder builder) {
      if (fileName == null) {
        return builder.getCurrentSkin() == null;
      }
      return fileName.equals(builder.getCurrentSkin());
    }

  }

  private static WebBuilder getBuilder(IlxWPort port) {
    return WebBuilder.getInstance(port.getRequest());
  }

}
