package model;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;

/**
 * @author Andréa
 * @version 1.0 25/03/11
 */
public class DAO {
    private static final java.util.logging.Logger logger =
            java.util.logging.Logger.getLogger(DAO.class.getCanonicalName());

    private static final Document singletonDOM = getDOMBDD();
    private static final XPath singletonXPath = getXPath();

    private static Document getDOMBDD() {
        try {
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder domBuilder = null;
            domBuilder = domFactory.newDocumentBuilder();
            return domBuilder.parse(
                    DAO.class.getClassLoader().getResourceAsStream("users.xml")
            );
        } catch (ParserConfigurationException e) {
            throw new Error("Database corrupted", e);
        } catch (SAXException e) {
            throw new Error("Database corrupted", e);
        } catch (IOException e) {
            throw new Error("Database not found", e);
        }
    }

    private static XPath getXPath() {
        XPathFactory xPathFactory = XPathFactory.newInstance();
        return xPathFactory.newXPath();
    }

    private static XPathExpression getUserXPathExpression(String login, String password) {
        try {
            return singletonXPath.compile(String.format("//user[login='%s' and password='%s']", login, password));
        } catch (XPathExpressionException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static XPathExpression getHashXPathExpression(String hash) {
        try {
            return singletonXPath.compile(String.format("//user[loginHash='%s']", hash));
        } catch (XPathExpressionException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static User loadUser(String login, String password) {
        try {
            NodeList users = (NodeList) getUserXPathExpression(login, password)
                    .evaluate(singletonDOM, XPathConstants.NODESET);
            logger.info("Evaluation set length : " + users.getLength());
            if (users.getLength() == 1) {
                return new User(login);
            } else {
                logger.warning("Duplicate users for (" + login + "," + password + ") : " + users.toString());
                for (int i = 0; i < users.getLength(); i++)
                    System.err.println("\t - Duplicated : " + users.item(i));
            }
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static User getUserByHash(String hash) {
        try {
            Node user = (Node) getHashXPathExpression(hash)
                    .evaluate(singletonDOM, XPathConstants.NODE);
            logger.info("Evaluation node : "+user);

            if (user != null) {
            logger.info(String.format("Evaluation node (%s;%s)",user.getNodeName(),user.getNodeValue()));
                return new User("andy");
            }
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return null;
    }
}
