/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_forms.hxx"

#include "model.hxx"

#include "model_helper.hxx"
#include "unohelper.hxx"
#include "binding.hxx"
#include "submission.hxx"
#include "mip.hxx"
#include "evaluationcontext.hxx"
#include "xmlhelper.hxx"
#include "datatyperepository.hxx"
#include "NameContainer.hxx"

#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.hxx>
#include <tools/debug.hxx>

#include <comphelper/propertysetinfo.hxx>
#include <cppuhelper/typeprovider.hxx>

#include <algorithm>

// UNO classes
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/xml/dom/XDocument.hpp>
#include <com/sun/star/xml/dom/XCharacterData.hpp>
#include <com/sun/star/xml/dom/NodeType.hpp>
#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/io/XInputStream.hpp>


using com::sun::star::lang::XMultiServiceFactory;
using com::sun::star::lang::XUnoTunnel;
using com::sun::star::beans::XPropertySet;
using com::sun::star::beans::PropertyValue;
using rtl::OUString;
using rtl::OUStringBuffer;
using com::sun::star::beans::PropertyVetoException;
using com::sun::star::beans::UnknownPropertyException;
using com::sun::star::util::VetoException;
using com::sun::star::lang::WrappedTargetException;
using com::sun::star::lang::IllegalArgumentException;
using com::sun::star::ucb::XSimpleFileAccess;
using com::sun::star::io::XInputStream;

using namespace com::sun::star::uno;
using namespace com::sun::star::xml::dom;
using namespace xforms;


#if OSL_DEBUG_LEVEL > 1
#define DBG_INVARIANT_TYPE(TYPE) class DBG_##TYPE { const TYPE* mpT; void check() { mpT->dbg_assertInvariant(); } public: DBG_##TYPE(const TYPE* pT) : mpT(pT) { check(); } ~DBG_##TYPE() { check(); } } _DBG_##TYPE(this);

#define DBG_INVARIANT() DBG_INVARIANT_TYPE(Model)
#else
#define DBG_INVARIANT_TYPE(TYPE)
#define DBG_INVARIANT()
#endif



//
// The Model
//

void Model::ensureAtLeastOneInstance()
{
    if( ! mpInstances->hasItems() )
    {
        // create a default instance
        newInstance( OUString(), OUString(), true );
    }
}



/** Model default constructor; create empty model */
Model::Model() :
    msID(),
    mpBindings( NULL ),
    mpSubmissions( NULL ),
    mpInstances( new InstanceCollection ),
    mxNamespaces( new NameContainer<OUString>() ),
    mxBindings( mpBindings ),
    mxSubmissions( mpSubmissions ),
    mxInstances( mpInstances ),
    mbInitialized( false ),
    mbExternalData( true )
{
    initializePropertySet();

    // initialize bindings collections
    // (not in initializer list to avoid use of incomplete 'this')
    mpBindings = new BindingCollection( this );
    mxBindings = mpBindings;

    mpSubmissions = new SubmissionCollection( this );
    mxSubmissions = mpSubmissions;

    // invariant only holds after construction
    DBG_INVARIANT();
}

Model::~Model() throw()
{
    // give up bindings & submissions; the mxBindings/mxSubmissions
    // references will then delete them
    mpBindings = NULL;
    mpSubmissions = NULL;
}

Model* lcl_getModel( const Reference<XUnoTunnel>& xTunnel )
{
    Model* pModel = NULL;
    if( xTunnel.is() )
        pModel = reinterpret_cast<Model*>(
            xTunnel->getSomething( Model::getUnoTunnelID() ) );
    return pModel;
}

Model* Model::getModel( const Reference<XModel>& xModel )
{
    return lcl_getModel( Reference<XUnoTunnel>( xModel, UNO_QUERY ) );
}

EvaluationContext Model::getEvaluationContext()
{
    // the default context is the top-level element node. A default
    // node (instanceData' is inserted when there is no default node
    Reference<XDocument> xInstance = getDefaultInstance();
    Reference<XNode> xElement( xInstance->getDocumentElement(), UNO_QUERY );

    // no element found? Then insert default element 'instanceData'
    if( ! xElement.is() )
    {
        xElement = Reference<XNode>(
                       xInstance->createElement( OUSTRING("instanceData") ),
                       UNO_QUERY_THROW );
        Reference<XNode>( xInstance, UNO_QUERY_THROW)->appendChild( xElement );
    }

    OSL_ENSURE( xElement.is() &&
                xElement->getNodeType() == NodeType_ELEMENT_NODE,
                "no element in evaluation context" );

    return EvaluationContext( xElement, this, mxNamespaces, 0, 1 );
}


Model::IntSequence_t Model::getUnoTunnelID()
{
    static cppu::OImplementationId aImplementationId;
    return aImplementationId.getImplementationId();
}

Model::XDocument_t Model::getForeignSchema() const
{
    return mxForeignSchema;
}

void Model::setForeignSchema( const XDocument_t& rDocument )
{
    mxForeignSchema = rDocument;
}

rtl::OUString Model::getSchemaRef() const
{
    return msSchemaRef;
}

void Model::setSchemaRef( const rtl::OUString& rSchemaRef )
{
    msSchemaRef = rSchemaRef;
}

Model::XNameContainer_t Model::getNamespaces() const
{
    return mxNamespaces;
}

void Model::setNamespaces( const XNameContainer_t& rNamespaces )
{
    if( rNamespaces.is() )
        mxNamespaces = rNamespaces;
}

bool Model::getExternalData() const
{
    return mbExternalData;
}

void Model::setExternalData( bool _bData )
{
    mbExternalData = _bData;
}

#if OSL_DEBUG_LEVEL > 1
void Model::dbg_assertInvariant() const
{
    OSL_ENSURE( mpInstances != NULL, "no instances found" );
    OSL_ENSURE( mxInstances.is(), "No instance container!" );
    //    OSL_ENSURE( mxInstances->hasElements(), "no instance!" );

    OSL_ENSURE( mpBindings != NULL, "no bindings element" );
    OSL_ENSURE( mxBindings.is(), "No Bindings container" );

    OSL_ENSURE( mpSubmissions != NULL, "no submissions element" );
    OSL_ENSURE( mxSubmissions.is(), "No Submission container" );



    /*
    // check bindings, and things that have to do with our binding
    std::vector<MIP*> aAllMIPs; // check MIP map
    sal_Int32 nCount = mpBindings->countItems();
    for( sal_Int32 i = 0; i < nCount; i++ )
    {
        Binding* pBind = Binding::getBinding(
            mpBindings->Collection<XPropertySet_t>::getItem( i ) );

        // examine and check binding
        OSL_ENSURE( pBind != NULL, "invalid binding found" );

        OSL_ENSURE( Model::getModel( pBind->getModel() ) == this,
                    "our binding doesn't know us.");
        // check this binding's MIP against MIP map
        MIP* pMIP = const_cast<MIP*>( pBind->_getMIP() );
        sal_Int32 nFound = 0;
        if( pMIP != NULL )
        {
            aAllMIPs.push_back( pMIP );
            for( MIPs_t::const_iterator aIter = maMIPs.begin();
                 aIter != maMIPs.end();
                 aIter++ )
            {
                if( pMIP == aIter->second )
                    nFound++;
            }
        }
        OSL_ENSURE( ( pMIP == NULL ) == ( nFound == 0 ), "MIP-map wrong" );
    }

    // check MIP map for left-over MIPs
    for( MIPs_t::const_iterator aIter = maMIPs.begin();
         aIter != maMIPs.end();
         aIter++ )
    {
        MIP* pMIP = aIter->second;
        std::vector<MIP*>::iterator aFound =
            std::find( aAllMIPs.begin(), aAllMIPs.end(), pMIP );
        if( aFound != aAllMIPs.end() )
            aAllMIPs.erase( aFound );
    }
    OSL_ENSURE( aAllMIPs.empty(), "lonely MIPs found!" );
    */
}
#endif


//
// MIP managment
//

void Model::addMIP( void* pTag, const XNode_t& xNode, const MIP& rMIP )
{
    OSL_ENSURE( pTag != NULL, "empty tag?" );
    OSL_ENSURE( xNode.is(), "no node" );

    MIPs_t::value_type aValue( xNode, ::std::pair<void*,MIP>( pTag, rMIP ) );
    maMIPs.insert( aValue );
}

void Model::removeMIPs( void* pTag )
{
    OSL_ENSURE( pTag != NULL, "empty tag?" );

    for( MIPs_t::iterator aIter = maMIPs.begin();
         aIter != maMIPs.end(); )
    {
        if( aIter->second.first == pTag )
        {
            MIPs_t::iterator next( aIter ); ++next;
            maMIPs.erase( aIter );
            aIter = next;
        }
        else
            ++aIter;
    }
}

MIP Model::queryMIP( const XNode_t& xNode ) const
{
    //    OSL_ENSURE( xNode.is(), "no node" );

    // travel up inheritance chain and inherit MIPs
    MIP aRet;
    for( XNode_t xCurrent = xNode;
         xCurrent.is();
         xCurrent = xCurrent->getParentNode() )
    {
        // iterate over all MIPs for this node, and join MIPs
        MIP aMIP;
        MIPs_t::const_iterator aEnd = maMIPs.upper_bound( xCurrent );
        MIPs_t::const_iterator aIter = maMIPs.lower_bound( xCurrent );
        for( ; aIter != aEnd; aIter++ )
          aMIP.join( aIter->second.second );

        // inherit from current node (or set if we are at the start node)
        if( xCurrent == xNode )
            aRet = aMIP;
        else
            aRet.inherit( aMIP );
    }

    return aRet;
}



void Model::rebind()
{
    OSL_ENSURE( mpBindings != NULL, "bindings?" );

    // iterate over all bindings and call update
    sal_Int32 nCount = mpBindings->countItems();
    for( sal_Int32 i = 0; i < nCount; i++ )
    {
        Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) );
        OSL_ENSURE( pBind != NULL, "binding?" );
        pBind->update();
    }
}



void Model::deferNotifications( bool bDefer )
{
    // iterate over all bindings and defer notifications
    sal_Int32 nCount = mpBindings->countItems();
    for( sal_Int32 i = 0; i < nCount; i++ )
    {
        Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) );
        OSL_ENSURE( pBind != NULL, "binding?" );
        pBind->deferNotifications( bDefer );
    }
}


bool Model::setSimpleContent( const XNode_t& xConstNode,
                              const rtl::OUString& sValue )
{
    OSL_ENSURE( xConstNode.is(), "need node to set data" );

    bool bRet = false;
    if( xConstNode.is() )
    {
        // non-const node reference so we can assign children (if necessary)
        XNode_t xNode( xConstNode );

        switch( xNode->getNodeType() )
        {
        case NodeType_ELEMENT_NODE:
        {
            // find first text node child
            Reference<XNode> xChild;
            for( xChild = xNode->getFirstChild();
                 xChild.is() && xChild->getNodeType() != NodeType_TEXT_NODE;
                 xChild = xChild->getNextSibling() )
                ; // empty loop; only find first text node child

            // create text node, if none is found
            if( ! xChild.is() )
            {
                xChild = Reference<XNode>(
                    xNode->getOwnerDocument()->createTextNode( OUString() ),
                    UNO_QUERY_THROW );
                xNode->appendChild( xChild );
            }
            xNode = xChild;

            OSL_ENSURE( xNode.is() &&
                        xNode->getNodeType() == NodeType_TEXT_NODE,
                        "text node creation failed?" );
        }
        // no break; continue as with text node:

        case NodeType_TEXT_NODE:
        case NodeType_ATTRIBUTE_NODE:
        {
            // set the node value (defer notifications)
            if( xNode->getNodeValue() != sValue )
            {
                deferNotifications( true );
                xNode->setNodeValue( sValue );
                deferNotifications( false );
            }
            bRet = true;
        }
        break;

        default:
        {
            OSL_ENSURE( false, "bound to unknown node type?" );
        }
        break;

        }
    }
    return bRet;
}

void Model::loadInstance( sal_Int32 nInstance )
{
    Sequence<PropertyValue> aSequence = mpInstances->getItem( nInstance );

    // find URL from instance
    OUString sURL;
    bool bOnce = false;
    getInstanceData( aSequence, NULL, NULL, &sURL, &bOnce );

    // if we have a URL, load the document and set it into the instance
    if( sURL.getLength() > 0 )
    {
        try
        {
            Reference<XInputStream> xInput =
                Reference<XSimpleFileAccess>(
                    createInstance(
                        OUSTRING("com.sun.star.ucb.SimpleFileAccess") ),
                    UNO_QUERY_THROW )->openFileRead( sURL );
            if( xInput.is() )
            {
                Reference<XDocument> xInstance =
                    getDocumentBuilder()->parse( xInput );
                if( xInstance.is() )
                {
                    OUString sEmpty;
                    setInstanceData( aSequence, NULL, &xInstance,
                                     bOnce ? &sEmpty : &sURL, NULL);
                    mpInstances->setItem( nInstance, aSequence );
                }
            }
        }
        catch( const Exception& )
        {
            // couldn't load the instance -> ignore!
        }
    }
}

void Model::loadInstances()
{
    // iterate over instance array to get PropertyValue-Sequence
    const sal_Int32 nInstances = mpInstances->countItems();
    for( sal_Int32 nInstance = 0; nInstance < nInstances; nInstance++ )
    {
        loadInstance( nInstance );
    }
}

bool Model::isInitialized() const
{
    return mbInitialized;
}

bool Model::isValid() const
{
    bool bValid = true;
    sal_Int32 nCount = mpBindings->countItems();
    for( sal_Int32 i = 0; bValid && i < nCount; i++ )
    {
        Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) );
        OSL_ENSURE( pBind != NULL, "binding?" );
        bValid = pBind->isValid();
    }
    return bValid;
}



//
// implement xforms::XModel
//

rtl::OUString Model::getID()
    throw( RuntimeException )
{
    DBG_INVARIANT();
    return msID;
}

void Model::setID( const rtl::OUString& sID )
    throw( RuntimeException )
{
    DBG_INVARIANT();
    msID = sID;
}

void Model::initialize()
    throw( RuntimeException )
{
    DBG_ASSERT( ! mbInitialized, "model already initialized" );

    // load instances
    loadInstances();

    // let's pretend we're initialized and rebind all bindings
    mbInitialized = true;
    rebind();
}

void Model::rebuild()
    throw( RuntimeException )
{
    if( ! mbInitialized )
        initialize();
    else
        rebind();
}

void Model::recalculate()
    throw( RuntimeException )
{
    rebind();
}

void Model::revalidate()
    throw( RuntimeException )
{
    // do nothing. We don't validate anyways!
}

void Model::refresh()
    throw( RuntimeException )
{
    rebind();
}


void SAL_CALL Model::submitWithInteraction(
    const rtl::OUString& sID,
    const XInteractionHandler_t& _rxHandler )
    throw( VetoException, 
           WrappedTargetException, 
           RuntimeException )
{
    DBG_INVARIANT();

    if( mpSubmissions->hasItem( sID ) )
    {
        Submission* pSubmission =
            Submission::getSubmission( mpSubmissions->getItem( sID ) );
        OSL_ENSURE( pSubmission != NULL, "no submission?" );
        OSL_ENSURE( pSubmission->getModel() == Reference<XModel>( this ),
                    "wrong model" );

        // submit. All exceptions are allowed to leave.
        pSubmission->submitWithInteraction( _rxHandler );
    }
}

void Model::submit( const rtl::OUString& sID )
    throw( VetoException, WrappedTargetException, RuntimeException )
{
    submitWithInteraction( sID, NULL );
}

Model::XDataTypeRepository_t SAL_CALL Model::getDataTypeRepository(  )
    throw( RuntimeException )
{
    if ( !mxDataTypes.is() )
        mxDataTypes = new ODataTypeRepository;

    return mxDataTypes;
}

//
// instance management
//

Model::XSet_t Model::getInstances()
    throw( RuntimeException )
{
    return mxInstances;
}

Model::XDocument_t Model::getInstanceDocument( const rtl::OUString& rName )
    throw( RuntimeException )
{
    ensureAtLeastOneInstance();
    Reference<XDocument> aInstance;
    sal_Int32 nInstance = lcl_findInstance( mpInstances, rName );
    if( nInstance != -1 )
        getInstanceData( mpInstances->getItem( nInstance ),
                         NULL, &aInstance, NULL, NULL );
    return aInstance;
}

Model::XDocument_t SAL_CALL Model::getDefaultInstance()
    throw( RuntimeException )
{
    ensureAtLeastOneInstance();
    DBG_ASSERT( mpInstances->countItems() > 0, "no instance?" );
    Reference<XDocument> aInstance;
    getInstanceData( mpInstances->getItem( 0 ), NULL, &aInstance, NULL, NULL );
    return aInstance;
}



//
// bindings management
//

Model::XPropertySet_t SAL_CALL Model::createBinding()
    throw( RuntimeException )
{
    DBG_INVARIANT();
    return new Binding();
}

Model::XPropertySet_t Model::cloneBinding( const XPropertySet_t& xBinding )
    throw( RuntimeException )
{
    DBG_INVARIANT();
    XPropertySet_t xNewBinding = createBinding();
    copy( xBinding, xNewBinding );
    return xNewBinding;
}

Model::XPropertySet_t Model::getBinding( const rtl::OUString& sId )
    throw( RuntimeException )
{
    DBG_INVARIANT();
    return mpBindings->hasItem( sId ) ? mpBindings->getItem( sId ) : NULL;
}

Model::XSet_t Model::getBindings()
    throw( RuntimeException )
{
    DBG_INVARIANT();
    return mxBindings;
}



//
// submission management
//

Model::XSubmission_t Model::createSubmission()
    throw( RuntimeException )
{
    DBG_INVARIANT();
    return new Submission();
}

Model::XSubmission_t Model::cloneSubmission(const XPropertySet_t& xSubmission)
    throw( RuntimeException )
{
    DBG_INVARIANT();
    XSubmission_t xNewSubmission = createSubmission();
    XPropertySet_t xAsPropertySet( xNewSubmission.get() );
    copy( xSubmission.get(), xAsPropertySet );
    return xNewSubmission;
}

Model::XSubmission_t Model::getSubmission( const rtl::OUString& sId )
    throw( RuntimeException )
{
    DBG_INVARIANT();
    XSubmission_t xSubmission;
    if ( mpSubmissions->hasItem( sId ) )
        xSubmission = xSubmission.query( mpSubmissions->getItem( sId ) );
    return xSubmission;
}

Model::XSet_t Model::getSubmissions()
    throw( RuntimeException )
{
    DBG_INVARIANT();
    return mxSubmissions;
}



//
// implementation of XFormsUIHelper1 interface
//   can be found in file model_ui.cxx
//



//
// implement XPropertySet & friends
//

#define HANDLE_ID 0
#define HANDLE_Instance 1
#define HANDLE_InstanceURL 2
#define HANDLE_ForeignSchema 3
#define HANDLE_SchemaRef 4
#define HANDLE_Namespaces 5
#define HANDLE_ExternalData 6

#define REGISTER_PROPERTY( property, type )   \
    registerProperty( PROPERTY( property, type ), \
    new DirectPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) );

#define REGISTER_PROPERTY_API( property, type )   \
    registerProperty( PROPERTY( property, type ), \
    new APIPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) );

#define REGISTER_BOOL_PROPERTY( property )   \
    registerProperty( PROPERTY( property, sal_Bool ), \
    new BooleanPropertyAccessor< Model, bool >( this, &Model::set##property, &Model::get##property ) );

void Model::initializePropertySet()
{
    REGISTER_PROPERTY_API ( ID,            OUString );
    REGISTER_PROPERTY     ( ForeignSchema, XDocument_t );
    REGISTER_PROPERTY     ( SchemaRef,     OUString );
    REGISTER_PROPERTY     ( Namespaces,    XNameContainer_t );
    REGISTER_BOOL_PROPERTY( ExternalData );
}

void Model::update()
    throw( RuntimeException )
{
    rebuild();
}


sal_Int64 Model::getSomething( const IntSequence_t& xId )
    throw( RuntimeException )
{
    return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL );
}

Sequence<sal_Int8> Model::getImplementationId()
    throw( RuntimeException )
{
    return getUnoTunnelID();
}


//
// 'shift' operators for getting data into and out of Anys
//

void operator <<= ( com::sun::star::uno::Any& rAny,
                    xforms::Model* pModel)
{
    Reference<XPropertySet> xPropSet( static_cast<XPropertySet*>( pModel ) );
    rAny <<= xPropSet;
}

bool operator >>= ( xforms::Model* pModel,
                    com::sun::star::uno::Any& rAny )
{
    bool bRet = false;

    // acquire model pointer through XUnoTunnel
    Reference<XUnoTunnel> xTunnel( rAny, UNO_QUERY );
    if( xTunnel.is() )
    {
        pModel = reinterpret_cast<xforms::Model*>(
            xTunnel->getSomething( xforms::Model::getUnoTunnelID() ) );
        bRet = true;
    }

    return bRet;
}
