/*
 * 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 eu.dnetlib.espas.util;

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

/**
 *
 * @author George Athanasopoulos <george.athanasopoulos, at UoA>
 */


public class MetadataValidator {
        public enum ValidityStatus {Valid, Invalid, Unsupported};
        
        private static DocumentBuilderFactory docFactory;
        private static final Logger _logger = Logger.getLogger(MetadataValidator.class);

        
        static{
            docFactory= DocumentBuilderFactory.newInstance();
            docFactory.setNamespaceAware(true);
        }
        
        
        /** Returns true if the provided serialized form of the gml:element is either an accepted point or polygon instance.
         */
        public static ValidityStatus isValidGMLLocation(String geomLocationChild){
            try {
            	
            	InputSource is = new InputSource();
        		is.setCharacterStream(new StringReader(geomLocationChild));
                Node locationDoc = docFactory.newDocumentBuilder().parse(is);
                Node elementNode = locationDoc.getFirstChild();

                return isValidGMLLocation(elementNode);

            } catch (Exception ex) {
                _logger.log(Priority.ERROR, null, ex);
                return ValidityStatus.Invalid;
            }
        }
        
        /** Returns true if the provided gml:element is either an accepted point or polygon instance.
         */
        public static ValidityStatus isValidGMLLocation(Node geomLocationChild){
                _logger.log(Priority.INFO, "Validating location gml element");
            try {
                String output = GeometryMetadataHandler.getGeoLocation(geomLocationChild);
                
                if(output.isEmpty())
                    return ValidityStatus.Unsupported;
                else if (output==null)
                    return ValidityStatus.Invalid;

                return ValidityStatus.Valid;
            } catch (Exception ex) {
                _logger.log(Priority.ERROR, null, ex);
                return ValidityStatus.Invalid;
            }
        }
        

        
        public static ValidityStatus isValidExtent(Node extentNode){
                _logger.log(Priority.INFO, "Validating gmd:extent element");
            try {
//                @todo: to update this implementation; an extent element may contain a list of geoextent, verticalextent and timeextent objects
                if(GeometryMetadataHandler.hasGeoExtent(extentNode) && GeometryMetadataHandler.getGeoExtent(extentNode).isEmpty())
                    return ValidityStatus.Unsupported;
                if(GeometryMetadataHandler.hasVerticalExtent(extentNode) &&  GeometryMetadataHandler.getVerticalExtentMax(extentNode).isEmpty() && GeometryMetadataHandler.getVerticalExtentMin(extentNode).isEmpty())
                    return ValidityStatus.Unsupported;
                if(TemporalMetadataHandler.hasTemporalExtent(extentNode) && TemporalMetadataHandler.getTemporalExtentStart(extentNode).isEmpty() && TemporalMetadataHandler.getTemporalExtentEnd(extentNode).isEmpty())
                    return ValidityStatus.Unsupported;
                return ValidityStatus.Valid;
            } catch (Exception ex) {
                _logger.log(Priority.ERROR, null, ex);
                return ValidityStatus.Invalid;
            }
        }
        

        
        public static ValidityStatus isValidGeoExtent(String geoExtentNode){
            try {
            	
            	InputSource is = new InputSource();
        		is.setCharacterStream(new StringReader(geoExtentNode));
                Node locationDoc = docFactory.newDocumentBuilder().parse(is);
                Node elementNode = locationDoc.getFirstChild();
                
                return isValidGeoExtent(elementNode);
            } catch (Exception ex) {
                _logger.log(Priority.ERROR, null, ex);
                return ValidityStatus.Invalid;
            }
            
        }

        public static ValidityStatus isValidGeoExtent(Node geoExtentNode){
                _logger.log(Priority.INFO, "Validating gmd:extent element");
            try {
                if(GeometryMetadataHandler.isGeoExtent(geoExtentNode) && GeometryMetadataHandler.getGeoExtent(geoExtentNode).isEmpty())
                    return ValidityStatus.Unsupported;
                return ValidityStatus.Valid;
            } catch (Exception ex) {
                _logger.log(Priority.ERROR, null, ex);
                return ValidityStatus.Invalid;
            }

        }
}
