/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.csu.sdmx.validation.model.dsds;

import cz.csu.sdmx.Utils;
import cz.csu.sdmx.validation.model.Dimension;
import cz.csu.sdmx.validation.xml.XmlHandler;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 *
 * @author themi
 */
public abstract class Dsd {
    public static final String COMPACT = "compact";
    public static final String UTILITY = "utility";
    public static final String CROSS = "cross";
    
    public static final String URI_DELIMITER = ":";
    
    protected Document data;
    protected List<Dimension> groupDimensions;
    protected List<Dimension> seriesDimensions;
    protected List<Dimension> obsDimensions;
    
    protected String datasetElementName;
    protected String groupElementName;
    protected String seriesElementName;
    protected String obsElementName;
    
    public Dsd(Document doc){
        this.data = doc;
        groupDimensions = new ArrayList<>();
        seriesDimensions = new ArrayList<>();
        obsDimensions = new ArrayList<>();
        
        extractDimensions(doc);
        
        System.out.println("------------Groups - " + groupElementName);
        for(Dimension d : groupDimensions){
            System.out.println(d.getName() + " - [" + Utils.join(d.getValidValues(), ",") + "]");
        }
        System.out.println("------------Series - " + seriesElementName);
        for(Dimension d : seriesDimensions){
            System.out.println(d.getName() + " - [" + Utils.join(d.getValidValues(), ",") + "]");
        }
        System.out.println("------------Obs - " + obsElementName);
        for(Dimension d : obsDimensions){
            System.out.println(d.getName() + " - [" + Utils.join(d.getValidValues(), ",") + "]");
        }
    }
    
    protected Element getSubElement(Document doc, String elementName){
        return Utils.getByXpath(doc, "//*[@substitutionGroup='"+elementName+"']");
    }
    
    protected List<Dimension> extractDimensions(Document doc, String typeName){
        return extractDimensions(doc, typeName, "attribute");
    }
    
    protected List<Dimension> extractDimensions(Document doc, String typeName, String parseFromEl){
        List<Dimension> dimensions = new ArrayList<>();
        
        Element seriesType = Utils.getByXpath(doc, "//*[@name='"+typeName+"']//*[contains(local-name(),'extension')]");
        NodeList attrsNodes = seriesType.getElementsByTagNameNS("*", parseFromEl);
        for(int i = 0; i < attrsNodes.getLength(); i++){
            Element attrEl = (Element)attrsNodes.item(i);
            String name = attrEl.getAttribute("name");
            String type = attrEl.getAttribute("type");
            String use = attrEl.getAttribute("use");
            boolean required;
            
            if(use == null)
                required = false;
            else{
                required = use.equals("required");
            }
        
            Element simpleType = Utils.getByXpath(doc, "//*[@name='"+type+"']");
            
            dimensions.add(new Dimension(name, required, parseSimpleType(simpleType)));
        }
        
        return dimensions;
    }
    
    protected List<String> parseSimpleType(Element simpleType){
        List<String> validValues = new ArrayList<>();

        if(simpleType != null){
            NodeList enumerations = simpleType.getElementsByTagNameNS("*","enumeration");
            for(int j = 0; j < enumerations.getLength(); j++){
                Element validVal = (Element)enumerations.item(j);
                validValues.add(validVal.getAttribute("value"));
            }
        }

        return validValues;
    }
    
    public List<Dimension> getSeriesDimensions() {
        return seriesDimensions;
    }
    
    public List<Dimension> getObsDimensions() {
        return obsDimensions;
    }
    
    protected abstract void extractDimensions(Document doc);
    
    public String getURN(){
        return (String) data.getUserData(XmlHandler.URN_KEY_NAME);
    }

    public Document getDocument() {
        return data;
    }
    
    public abstract String getType();

    public List<Dimension> getGroupDimensions() {
        return groupDimensions;
    }

    public String getDatasetElementName() {
        return datasetElementName;
    }

    public String getGroupElementName() {
        return groupElementName;
    }

    public String getSeriesElementName() {
        return seriesElementName;
    }

    public String getObsElementName() {
        return obsElementName;
    }
    
}
