/* OdLib_Css- Copyright (c) 2007-2020 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.opendocument.css.parse;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import net.mapeadores.opendocument.elements.ElementMaps;
import net.mapeadores.opendocument.elements.OdLibException;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.Parser;
import org.w3c.css.sac.helpers.ParserFactory;


/**
 *
 * @author Vincent Calame
 */
public class CssParser {

    public final static CssErrorHandler NULL_ERRORHANDLER = new NullErrorHandler();
    public final static CssErrorHandler OUT_ERRORHANDLER = new OutErrorHandler();

    public CssParser() {
    }

    public static ElementMaps parse(CssSource cssSource, CssErrorHandler errorHandler) throws IOException {
        if (errorHandler == null) {
            errorHandler = NULL_ERRORHANDLER;
        }
        Reader reader = cssSource.getReader();
        InputSource inputSource = new InputSource(reader);
        OdCssDocumentHandler documentHandler = new OdCssDocumentHandler();
        ParserFactory parserFactory = new ParserFactory();
        try {
            Parser parser = parserFactory.makeParser();
            parser.setDocumentHandler(documentHandler);
            parser.setErrorHandler(errorHandler);
            errorHandler.setCurrentURI(cssSource.getCssSourceURI());
            parser.parseStyleSheet(inputSource);
        } catch (ClassNotFoundException nf) {
            throw new OdLibException(nf);
        } catch (IllegalAccessException nf) {
            throw new OdLibException(nf);
        } catch (InstantiationException nf) {
            throw new OdLibException(nf);
        }
        ElementMaps elementMaps = documentHandler.getElementMaps();
        List<String> list = documentHandler.getImportList();
        int size = list.size();
        if (size > 0) {
            for (int i = (size - 1); i >= 0; i--) {
                String url = list.get(i);
                CssSource importSource = cssSource.getImportCssSource(url);
                if (importSource != null) {
                    ElementMaps importElementMaps = parse(importSource, errorHandler);
                    elementMaps.append(importElementMaps);
                }
            }
        }
        return elementMaps;
    }

    public static ElementMaps parse(File file, CssErrorHandler errorHandler) throws IOException {
        FileCssSource cssSource = new FileCssSource(file);
        return parse(cssSource, errorHandler);
    }

    public static ElementMaps parseDist(Class referenceClass, String path, CssErrorHandler cssErrorHandler) throws IOException {
        return CssParser.parse(new DistCssSource(referenceClass, path), cssErrorHandler);
    }


    private static class NullErrorHandler implements CssErrorHandler {

        private NullErrorHandler() {

        }

        @Override
        public void setCurrentURI(String uri) {
        }

        @Override
        public void error(CSSParseException exception) throws CSSException {
        }

        @Override
        public void fatalError(CSSParseException exception) throws CSSException {
        }

        @Override
        public void warning(CSSParseException exception) throws CSSException {
        }

        @Override
        public void unknownURIFatalError(String uri) {

        }

    }


    private static class OutErrorHandler implements CssErrorHandler {

        private String currentURI;

        public OutErrorHandler() {
        }

        @Override
        public void setCurrentURI(String uri) {
            this.currentURI = uri;
        }

        @Override
        public void error(CSSParseException exception) throws CSSException {
            System.out.println(currentURI + " / " + exception.getMessage());
        }

        @Override
        public void fatalError(CSSParseException exception) throws CSSException {
            System.out.println(currentURI + " / " + exception.getMessage());
        }

        @Override
        public void warning(CSSParseException exception) throws CSSException {
            System.out.println(currentURI + " / " + exception.getMessage());
        }

        @Override
        public void unknownURIFatalError(String uri) {
            System.out.println(uri + " / Unknown URI");
        }

    }

}
