/*
 *  RuleManager.java
 * 
 *  RELOAD Editor - An IMS Metadata, Content Packaging and Learning Design tool 
 *  with ADAPTATION AT ACTIVITY LEVEL
 *
 *  Copyright (c) 2006 Miguel Fern�ndez Lores
 *
 *  Technical Contact:
 *  Miguel Fernandez Lores
 *  e-mail: tucias@hotmail.com
 *
 */

package uk.ac.reload.editor.scormadaptive.rules.jdom.rule;

import uk.ac.reload.editor.scormadaptive.rules.syntax.Rule;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Element;
import org.jdom.Namespace;

/**
 * This class is an intermediate class to read the adaptation 
 * rules. It is used by the Assistant to read and  to transform the 
 * JDOM tree sent by Reload
 *
 * @author  lagar
 * @version 0.2 
 */
public class RuleManager {
    
    /**
     * Reference to the rule loaded in the assistant. Index in oRules ArrayList
     */
    public int iRuleSelected;
    
    /**
     * List of adaptation rules 
     */
    private ArrayList<Rule> oRules;
    
    /**
     * Father Element
     */
    private Element oFatherEl;
    
    /**
     * Adaptation Element
     */
    private Element oAdapEl;
    
    /** 
     * Creates a new instance of RuleManager 
     */
    public RuleManager(Element oEl, Namespace namespace) throws Exception{
        oFatherEl = oEl;
        boolean bEmpty = true;
        Element oAdaptElement = oFatherEl.getChild("adaptation", Namespace.getNamespace("http://idtv.det.uvigo.es"));  
        java.util.List previusElements = oAdaptElement.getChildren();
        if (previusElements == null || previusElements.size() <= 0) 
        	bEmpty = true;
        else
        	bEmpty = false;

        
        //Miramos si este elemento tiene un hijo <adaptation>
        oAdapEl = oFatherEl.getChild("adaptation", Namespace.getNamespace("http://idtv.det.uvigo.es"));
        //Si no tiene inicializamos oRules

        if (bEmpty) oRules = null;
        else {
            Element oAdapRulesEl = oAdapEl.getChild("adaptationRules");
            if ((oAdapRulesEl == null)||(oAdapRulesEl.getChildren("rule") == null)) {
                throw new Exception("Rule Manager: Element <adaptationRules> " +
                        "and Child Elements <rule> are mandatory");
            }
            else {
                List oRuleList = oAdapRulesEl.getChildren("rule");
                Iterator oItt = oRuleList.iterator();
                int i = 1;
                while (oItt.hasNext()){
                    Element oElAux= (Element)oItt.next();
                    addRule(readTreeRule(oElAux, i));
                    i++;
                }
            }
        }
    }
    
    /**
     * Devuelve la regla de adaptaci�n indicada
     * por iIndex;
     *
     * @param iIndes El indice de la regla
     * @return La regla de adaptacion. Null si no existe
     */
    public Rule getRule(int iIndex) {
        if (oRules ==null) return null;
        else return oRules.get(iIndex);
    }
    
    /**
     * Este metodo permite desplazar (alterar) el orden de una regla
     * en el Array de reglas.
     * @param bArriba Si es true la regla se deplaza una posici�n hacia arriba (a indices menores). Si es false hacia abajo (hacia indices mayores).
     * @param iIndex El indice de la regla que se desplaza
     */
    public void moveRule(boolean bArriba,int iIndex) {
        if (bArriba) {
            if (iIndex==0) return;
            Rule oTemp = oRules.get(iIndex-1);
            oRules.set(iIndex-1,oRules.get(iIndex));
            oRules.set(iIndex,oTemp);
        } else {
            if (iIndex==oRules.size()-1) return;
            Rule oTemp = oRules.get(iIndex+1);
            oRules.set(iIndex+1,oRules.get(iIndex));
            oRules.set(iIndex,oTemp);
        }
    }
    
    
    /**
     * Anade la regla de adaptacion indicada
     *
     * @param oRule La regla a anadir
     */
    public void addRule(Rule oRule) {
        if (oRules==null) {
            oRules = new java.util.ArrayList<Rule>();
            oRules.add(oRule);
        } else oRules.add(oRule);
    }
    
    public void addRule(Rule oRule, int iIndex) {
        //En este caso oRules nunca va a ser null
        //Porque se llama despues de crear la Rule Default
        oRules.add(iIndex, oRule);
    }
    
    /**
     * Indica el numero de reglas de oRules
     */
    public int sizeRules() {
        if (oRules==null) return 0;
        return oRules.size();
    }
    
    /**
     * Elimina la regla de oRules
     * @param iIndex El indice de la regla a borrar
     */
    public void removeRule(int iIndex) {
        if (iIndex<0 || iIndex >= oRules.size()) return;
        oRules.remove(iIndex);
    }
    
    public Element getAdaptationElement(){
        return oAdapEl;
    }

    public Rule readTreeRule(Element oElAux, int iNumRule) throws Exception {
        
        Element eRCs = oElAux.getChild("ruleConditions");
        Element eRA = oElAux.getChild("ruleAction");
        //Estos childs son obligatorios
        if ((eRCs == null) || (eRA == null)) {
                throw new Exception("Rule Manager: Element <ruleConditions> " +
                        "and Element <ruleAction> are mandatory");
        }
        
        RuleConditions oRCs = new RuleConditions(eRCs);
        ruleAction oRA = new ruleAction(eRA);
        //Los nombres son del tipo Rule+num
        String sName;
        if (oRCs.isDefault()) sName = "Default";
        else sName = oElAux.getAttributeValue("name");
        
        //else sName = "Rule" + Integer.toString(iNumRule);
        
        int iLast = 0;
        String[] sRuleRC = oRCs.getText();
        String[] sRuleAct = oRA.getText();
        String[] sRuleTextAux = new String[sRuleRC.length + sRuleAct.length];
        for (int j=0; j<sRuleRC.length;j++) {
            if (sRuleRC[j] != null) {
                sRuleTextAux[iLast] = sRuleRC[j];
                iLast++;
            }
        }
           
        for (int i=0; i<sRuleAct.length; i++) {
            if (sRuleAct[i] != null) {
                sRuleTextAux[iLast] = sRuleAct[i];
                iLast++;
            }
        }
        String [] sRuleText = new String[iLast];
        for (int i = 0; i<iLast; i++) sRuleText[i] = sRuleTextAux[i];
        Rule oRule = new Rule(sName, sRuleText, eRCs, eRA);        
        return oRule;
    }
    
    public void addRuleConditions(RuleConditions orc){
        oRules.get(iRuleSelected).setRuleConditions(orc);
    }

}
