/* 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.obr.plugin;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


/**
 * this class parse the old repository.xml file build the bundle resource description and update the repository.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ObrUpdate
{
    /**
     * generate the date format to insert it in repository descriptor file.
     */
    static SimpleDateFormat m_format = new SimpleDateFormat( "yyyyMMddHHmmss.SSS" );

    /**
     * logger for this plugin.
     */
    private Log m_logger;

    /**
     * name and path to the repository descriptor file.
     */
    private URI m_repositoryXml;

    /**
     * name and path to the obr.xml file.
     */
    private URI m_obrXml;

    /**
     * name and path to the bundle jar file.
     */
    private URI m_bundlePath;

    /**
     * maven project description.
     */
    private MavenProject m_project;

    /**
     * user configuration information.
     */
    private Config m_userConfig;

    /**
     * used to build another xml document.
     */
    private DocumentBuilder m_documentBuilder;

    /**
     * root on parent document.
     */
    private Document m_repositoryDoc;

    /**
     * used to store bundle information.
     */
    private ResourcesBundle m_resourceBundle;

    /**
     * base URI used to relativize bundle URIs.
     */
    private URI m_baseURI;


    /**
     * initialize information.
     * @param repositoryXml path to the repository descriptor file
     * @param obrXml path and filename to the obr.xml file
     * @param project maven project description
     * @param bundlePath path to the bundle jar file
     * @param mavenRepositoryPath path to the local maven repository
     * @param userConfig user information
     * @param logger plugin logger
     */
    public ObrUpdate( PathFile repositoryXml, URI obrXml, MavenProject project, String bundlePath,
        String mavenRepositoryPath, Config userConfig, Log logger )
    {
        // m_localRepo = localRepo;
        m_bundlePath = ObrUtils.toFileURI( bundlePath );
        m_repositoryXml = repositoryXml.getFile().toURI(); // FIXME: remove when PathFile is gone
        m_obrXml = obrXml;
        m_project = project;
        m_logger = logger;

        m_userConfig = userConfig;

        m_resourceBundle = new ResourcesBundle( logger );

        if ( userConfig.isRemotely() )
        {
            m_baseURI = ObrUtils.toFileURI( mavenRepositoryPath );
        }
        else
        {
            m_baseURI = m_repositoryXml;
        }
    }


    /**
     * update the repository descriptor file. parse the old repository descriptor file, get the old reference of the bundle or determine the id for a new bundle, extract information from bindex set the new information in descriptor file and save it.
     * @throws MojoExecutionException if the plugin failed
     */
    public void updateRepository() throws MojoExecutionException
    {

        m_logger.debug( " (f) m_obrXml = " + m_obrXml );
        m_logger.debug( " (f) m_bundlePath = " + m_bundlePath );
        m_logger.debug( " (f) m_repositoryXml = " + m_repositoryXml );

        m_documentBuilder = initDocumentBuilder();

        if ( m_documentBuilder == null )
        {
            return;
        }

        // get the file size
        File bundleFile = new File( m_bundlePath );
        if ( bundleFile.exists() )
        {
            URI bundleURI = m_bundlePath;
            if ( m_userConfig.isPathRelative() )
            {
                bundleURI = ObrUtils.getRelativeURI( m_baseURI, bundleURI );
            }

            m_resourceBundle.setSize( String.valueOf( bundleFile.length() ) );
            m_resourceBundle.setUri( bundleURI.toASCIIString() );
        }
        else
        {
            m_logger.error( "file doesn't exist: " + m_bundlePath );
            return;
        }

        // parse repository
        if ( parseRepositoryXml() == -1 )
        {
            return;
        }

        // parse the obr.xml file
        if ( m_obrXml != null )
        {
            // URL url = getClass().getResource("/SchemaObr.xsd");
            // TODO validate obr.xml file

            Document obrXmlDoc = parseFile( m_obrXml, m_documentBuilder );
            if ( obrXmlDoc == null )
            {
                return;
            }
            Node obrXmlRoot = ( Element ) obrXmlDoc.getDocumentElement();
            // sort the obr file
            sortObrXml( obrXmlRoot );
        }

        ExtractBindexInfo bindexExtractor;
        try
        {
            // use bindex to extract bundle information
            bindexExtractor = new ExtractBindexInfo( m_repositoryXml, m_bundlePath.getPath() );
        }
        catch ( MojoExecutionException e )
        {
            m_logger.error( "unable to build Bindex informations" );
            e.printStackTrace();
            throw new MojoExecutionException( "MojoFailureException" );
        }

        m_resourceBundle.construct( m_project, bindexExtractor );

        Element rootElement = m_repositoryDoc.getDocumentElement();
        if ( !walkOnTree( rootElement ) )
        {
            // the correct resource node was not found, we must create it
            // we compute the new id
            String id = m_resourceBundle.getId();
            searchRepository( rootElement, id );
        }

        // the repository.xml file have been modified, so we save it
        m_logger.info( "Writing OBR metadata" );
        writeToFile( m_repositoryXml, rootElement );
    }


    /**
     * init the document builder from xerces.
     * @return DocumentBuilder ready to create new document
     */
    private DocumentBuilder initDocumentBuilder()
    {
        DocumentBuilder documentBuilder = null;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try
        {
            documentBuilder = factory.newDocumentBuilder();
        }
        catch ( ParserConfigurationException e )
        {
            m_logger.error( "unable to create a new xml document" );
            e.printStackTrace();
        }
        return documentBuilder;

    }


    /**
     * Parse the repository descriptor file.
     * 
     * @return 0 if the bundle is already in the descriptor, else -1
     * @throws MojoExecutionException if the plugin failed
     */
    private int parseRepositoryXml() throws MojoExecutionException
    {

        File fout = new File( m_repositoryXml );
        if ( !fout.exists() )
        {
            Document doc = m_documentBuilder.newDocument();

            // create xml tree
            Date d = new Date();
            d.setTime( System.currentTimeMillis() );
            Element root = doc.createElement( "repository" );
            root.setAttribute( "lastmodified", m_format.format( d ) );
            root.setAttribute( "name", "MyRepository" );
            try
            {
                writeToFile( m_repositoryXml, root );
            }
            catch ( MojoExecutionException e )
            {
                e.printStackTrace();
                throw new MojoExecutionException( "MojoExecutionException" );
            }
        }

        // now we parse the repository.xml file
        m_repositoryDoc = parseFile( m_repositoryXml, m_documentBuilder );
        if ( m_repositoryDoc == null )
        {
            return -1;
        }

        return 0;
    }


    /**
     * transform a xml file to a xerces Document.
     * @param filename path to the xml file
     * @param documentBuilder DocumentBuilder get from xerces
     * @return Document which describe this file
     */
    private Document parseFile( URI filename, DocumentBuilder documentBuilder )
    {
        if ( documentBuilder == null )
        {
            return null;
        }
        // The document is the root of the DOM tree.
        m_logger.info( "Parsing " + filename );
        Document doc = null;
        try
        {
            doc = documentBuilder.parse( new File( filename ) );
        }
        catch ( SAXException e )
        {
            e.printStackTrace();
            return null;
        }
        catch ( IOException e )
        {
            m_logger.error( "cannot open file: " + filename );
            e.printStackTrace();
            return null;
        }
        return doc;
    }


    /**
     * put the information from obr.xml into ressourceBundle object.
     * @param node Node to the OBR.xml file
     */
    private void sortObrXml( Node node )
    {
        if ( node.getNodeName().compareTo( "require" ) == 0 )
        {
            Require newRequireNode = new Require();
            NamedNodeMap list = node.getAttributes();
            try
            {
                newRequireNode.setExtend( list.getNamedItem( "extend" ).getNodeValue() );
                newRequireNode.setMultiple( list.getNamedItem( "multiple" ).getNodeValue() );
                newRequireNode.setOptional( list.getNamedItem( "optional" ).getNodeValue() );
                newRequireNode.setFilter( list.getNamedItem( "filter" ).getNodeValue() );
                newRequireNode.setName( list.getNamedItem( "name" ).getNodeValue() );
            }
            catch ( NullPointerException e )
            {
                m_logger
                    .error( "the obr.xml file seems to be invalid in a \"require\" tag (one or more attributes are missing)" );
                // e.printStackTrace();
            }
            newRequireNode.setValue( XmlHelper.getTextContent( node ) );
            m_resourceBundle.addRequire( newRequireNode );
        }
        else if ( node.getNodeName().compareTo( "capability" ) == 0 )
        {
            Capability newCapability = new Capability();
            try
            {
                newCapability.setName( node.getAttributes().getNamedItem( "name" ).getNodeValue() );
            }
            catch ( NullPointerException e )
            {
                m_logger.error( "attribute \"name\" is missing in obr.xml in a \"capability\" tag" );
                e.printStackTrace();
            }
            NodeList list = node.getChildNodes();
            for ( int i = 0; i < list.getLength(); i++ )
            {
                PElement p = new PElement();
                Node n = list.item( i );
                Node item = null;
                // System.err.println(n.getNodeName());
                if ( n.getNodeName().compareTo( "p" ) == 0 )
                {

                    p.setN( n.getAttributes().getNamedItem( "n" ).getNodeValue() );
                    item = n.getAttributes().getNamedItem( "t" );
                    if ( item != null )
                    {
                        p.setT( item.getNodeValue() );
                    }
                    item = n.getAttributes().getNamedItem( "v" );
                    if ( item != null )
                    {
                        p.setV( item.getNodeValue() );
                    }

                    newCapability.addP( p );
                }
            }
            m_resourceBundle.addCapability( newCapability );
        }
        else if ( node.getNodeName().compareTo( "category" ) == 0 )
        {
            Category newCategory = new Category();
            newCategory.setId( node.getAttributes().getNamedItem( "id" ).getNodeValue() );
            m_resourceBundle.addCategory( newCategory );
        }
        else
        {
            NodeList list = node.getChildNodes();
            for ( int i = 0; i < list.getLength(); i++ )
            {
                sortObrXml( list.item( i ) );
            }
        }
    }


    /**
     * write a Node in a xml file.
     * @param outputFilename URI to the output file
     * @param treeToBeWrite Node root of the tree to be write in file
     * @throws MojoExecutionException if the plugin failed
     */
    private void writeToFile( URI outputFilename, Node treeToBeWrite ) throws MojoExecutionException
    {
        // init the transformer
        Transformer transformer = null;
        TransformerFactory tfabrique = TransformerFactory.newInstance();
        try
        {
            transformer = tfabrique.newTransformer();
        }
        catch ( TransformerConfigurationException e )
        {
            m_logger.error( "Unable to write to file: " + outputFilename.toString() );
            e.printStackTrace();
            throw new MojoExecutionException( "TransformerConfigurationException" );
        }
        Properties proprietes = new Properties();
        proprietes.put( "method", "xml" );
        proprietes.put( "version", "1.0" );
        proprietes.put( "encoding", "ISO-8859-1" );
        proprietes.put( "standalone", "yes" );
        proprietes.put( "indent", "yes" );
        proprietes.put( "omit-xml-declaration", "no" );
        transformer.setOutputProperties( proprietes );

        DOMSource input = new DOMSource( treeToBeWrite );

        File fichier = new File( outputFilename );
        fichier.getParentFile().mkdirs();
        FileOutputStream flux = null;
        try
        {
            flux = new FileOutputStream( fichier );
        }
        catch ( FileNotFoundException e )
        {
            m_logger.error( "Unable to write to file: " + fichier.getName() );
            e.printStackTrace();
            throw new MojoExecutionException( "FileNotFoundException" );
        }
        Result output = new StreamResult( flux );
        try
        {
            transformer.transform( input, output );
        }
        catch ( TransformerException e )
        {
            e.printStackTrace();
            throw new MojoExecutionException( "TransformerException" );
        }

        try
        {
            flux.flush();
            flux.close();
        }
        catch ( IOException e )
        {
            e.printStackTrace();
            throw new MojoExecutionException( "IOException" );
        }

    }


    /**
     * walk on the tree until the targeted node was found.
     * @param node targeted node
     * @return true if the requiered node was found else false.
     */
    private boolean walkOnTree( Node node )
    {

        if ( node.getNodeName().compareTo( "resource" ) == 0 )
        {
            return resource( node );
        }
        else
        { // look at the repository node (first in the file)
            if ( node.getNodeName().compareTo( "repository" ) == 0 )
            {
                Date d = new Date();
                d.setTime( System.currentTimeMillis() );
                NamedNodeMap nList = node.getAttributes();
                Node n = nList.getNamedItem( "lastmodified" );
                n.setNodeValue( m_format.format( d ) );
            }
            NodeList list = node.getChildNodes();
            if ( list.getLength() > 0 )
            {
                for ( int i = 0; i < list.getLength(); i++ )
                {
                    if ( walkOnTree( list.item( i ) ) )
                    {
                        return true;
                    }
                }
            }
            return false;
        }

    }


    /**
     * put the resource bundle in the tree.
     * @param node Node on the xml file
     * @param id id of the bundle ressource
     */
    private void searchRepository( Node node, String id )
    {
        if ( node.getNodeName().compareTo( "repository" ) == 0 )
        {
            node.appendChild( m_resourceBundle.getNode( m_repositoryDoc ) );
            return;
        }
        else
        {
            System.out.println( "Second branch..." );
            NodeList list = node.getChildNodes();
            if ( list.getLength() > 0 )
            {
                for ( int i = 0; i < list.getLength(); i++ )
                {
                    searchRepository( list.item( i ), id );
                }
            }
        }

    }


    /**
     * compare two node and update the array which compute the smallest free id.
     * @param node : node
     * @return true if the node is the same bundle than the ressourceBundle, else false.
     */
    private boolean resource( Node node )
    {

        // this part save all the id free if we need to add resource
        String id = node.getAttributes().getNamedItem( "id" ).getNodeValue();
        NamedNodeMap map = node.getAttributes();

        if ( m_resourceBundle.isSameBundleResource( map.getNamedItem( "symbolicname" ).getNodeValue(), map
            .getNamedItem( "version" ).getNodeValue() ) )
        {
            m_resourceBundle.setId( String.valueOf( id ) );
            node.getParentNode().replaceChild( m_resourceBundle.getNode( m_repositoryDoc ), node );
            return true;
        }
        return false;
    }
}
