package org.ametys.cms;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.cocoon.components.source.impl.SitemapSource;
import org.apache.commons.io.IOUtils;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.xml.dom.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import org.ametys.runtime.util.JSONUtils;

public class EditContentHelper implements Component, Serviceable
{
    private SourceResolver _sourceResolver;
    private DOMParser _domParser;
    private JSONUtils _jsonUtils;

    @Override
    public void service(ServiceManager manager) throws ServiceException
    {
        _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
        _domParser = (DOMParser) manager.lookup(DOMParser.ROLE);
        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
    }
    
    /**
     * Edit a content by using the workflow action
     * @param workflowAction The action of workflow to use to edit this content (e.g. '2')
     * @param jsonPath The source path to a json file containing what edit content function is awaiting
     * @return The error messages encountered.
     * @throws IOException 
     * @throws MalformedURLException 
     * @throws SAXException 
     */
    public Map<String, Object> editContent(int workflowAction, String jsonPath) throws MalformedURLException, IOException, SAXException
    {
        Source source = null;
        InputStream is = null;
        try
        {
            source = _sourceResolver.resolveURI(jsonPath);
            is = source.getInputStream();
            String jsonString = IOUtils.toString(is);
            Map<String, Object> jsParameters = _jsonUtils.convertJsonToMap(jsonString);
            return editContent(workflowAction, jsParameters);
        }   
        finally
        {
            IOUtils.closeQuietly(is);
            _sourceResolver.release(source);
        }
    }
    
    /**
     * Edit a content by using the workflow action
     * @param workflowAction The action of workflow to use to edit this content (e.g. '2')
     * @param jsParameters The parameters sent by a client to the workflow functions.
     * @return The error messages encountered.
     * @throws IOException 
     * @throws MalformedURLException 
     * @throws SAXException 
     */
    public Map<String, Object> editContent(int workflowAction, Map<String, Object> jsParameters) throws MalformedURLException, IOException, SAXException
    {
        Document doc;
        SitemapSource source = null;
        InputStream iStream = null;
        try
        {
            source = (SitemapSource) _sourceResolver.resolveURI("cocoon://plugins/cms/do-action/" + workflowAction, null, jsParameters);
            iStream = source.getInputStream();
            System.out.println(IOUtils.toString(iStream));iStream.reset();
            doc = _domParser.parseDocument(new InputSource(iStream));
        }
        finally
        {
            IOUtils.closeQuietly(iStream);
            _sourceResolver.release(source);
        }
        
        Map<String, Object> errors = new HashMap<String, Object>();
        
        Node node = doc.getFirstChild().getFirstChild();
        do 
        {
            Node subNode;
            if (node.getNodeType() == 1 && (subNode = node.getFirstChild()) != null && subNode.getNodeType() == 1)
            {
                errors.put(node.getNodeName(), subNode.getTextContent());
            }
        }
        while ((node = node.getNextSibling()) != null);
        
        return errors;
    }
}
