/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */

#ifndef INCLUDED_XMLOFF_XMLSTYLE_HXX
#define INCLUDED_XMLOFF_XMLSTYLE_HXX

#include <sal/config.h>
#include <xmloff/dllapi.h>
#include <sal/types.h>
#include <xmloff/xmlictxt.hxx>
#include <xmloff/families.hxx>
#include <vector>
#include <memory>

class SvXMLStylesContext_Impl;
class SvXMLImportPropertyMapper;

namespace com::sun::star {
namespace container { class XNameContainer; }
namespace style { class XAutoStyleFamily; }
}

class XMLOFF_DLLPUBLIC SvXMLStyleContext : public SvXMLImportContext
{
    OUString     maName;
    OUString     maDisplayName;
    css::uno::Any maAutoName;
    OUString     maParentName;// Will be moved to XMLPropStyle soon!!!!
    OUString     maFollow;    // Will be moved to XMLPropStyle soon!!!!
    OUString     maLinked;
    bool         mbHidden;

    XmlStyleFamily mnFamily;

    bool         mbValid : 1; // Set this to false in CreateAndInsert
                              // if the style shouldn't be processed
                              // by Finish() or is somehow invalid.
    bool         mbNew : 1;   // Set this to false in CreateAnsInsert
                              // if the style is already existing.
    bool         mbDefaultStyle : 1;

protected:

    virtual void SetAttribute( sal_Int32 nElement, const OUString& rValue );

    void SetFamily( XmlStyleFamily nSet ) { mnFamily = nSet; }
    void SetAutoName( const css::uno::Any& rName ) { maAutoName = rName; }

public:

    SvXMLStyleContext( SvXMLImport& rImport,
              XmlStyleFamily nFamily=XmlStyleFamily::DATA_STYLE,
              bool bDefaultStyle = false );

    virtual ~SvXMLStyleContext() override;

    virtual void SAL_CALL startFastElement(
            sal_Int32 nElement,
            const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) override final;

    const OUString&  GetName() const { return maName; }
    const OUString&  GetDisplayName() const { return maDisplayName.getLength() ? maDisplayName : maName; }
    const css::uno::Any& GetAutoName() const { return maAutoName; }
    const OUString&  GetParentName() const { return maParentName; }
    const OUString&  GetFollow() const { return maFollow; }
    const OUString&  GetLinked() const { return maLinked; }

    XmlStyleFamily GetFamily() const { return mnFamily; }

    bool IsValid() const { return mbValid; }
    void SetValid( bool b ) { mbValid = b; }

    bool IsNew() const { return mbNew; }
    void SetNew( bool b ) { mbNew = b; }

    bool IsHidden() const { return mbHidden; }

    // This method is called for every default style
    virtual void SetDefaults();

    // This method is called for every style. It must create it and insert
    // it into the document.
    virtual void CreateAndInsert( bool bOverwrite );

    // This method is called for every style. It must create it and insert
    // it into the document if this hasn't happened already in CreateAndInsert().
    virtual void CreateAndInsertLate( bool bOverwrite );

    // This method is called for every style after all styles have been
    // inserted into the document.
    virtual void Finish( bool bOverwrite );

    bool IsDefaultStyle() const { return mbDefaultStyle; }

    /** if this method returns true, its parent styles context
        should not add it to its container.<br>
        Transient styles can't be accessed from its
        parent SvXMLStylesContext after they are imported and
        the methods CreateAndInsert(), CreateAndInsertLate()
        and Finish() will not be called.
        The default return value is false
    */
    virtual bool IsTransient() const;
};

class XMLOFF_DLLPUBLIC SvXMLStylesContext : public SvXMLImportContext
{
    std::unique_ptr<SvXMLStylesContext_Impl> mpImpl;


    css::uno::Reference< css::container::XNameContainer > mxParaStyles;

    css::uno::Reference< css::container::XNameContainer > mxTextStyles;

    css::uno::Reference< css::style::XAutoStyleFamily > mxParaAutoStyles;

    css::uno::Reference< css::style::XAutoStyleFamily > mxTextAutoStyles;

    mutable std::unique_ptr < SvXMLImportPropertyMapper > mxChartImpPropMapper;
    mutable std::unique_ptr < SvXMLImportPropertyMapper > mxPageImpPropMapper;

    SvXMLStylesContext(SvXMLStylesContext const &) = delete;
    SvXMLStylesContext& operator =(SvXMLStylesContext const &) = delete;

protected:

    sal_uInt32 GetStyleCount() const;
    SvXMLStyleContext *GetStyle( sal_uInt32 i );
    const SvXMLStyleContext *GetStyle( sal_uInt32 i ) const;

    virtual SvXMLStyleContext *CreateStyleChildContext(
        sal_Int32 nElement,
        const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );

    virtual SvXMLStyleContext *CreateStyleStyleChildContext( XmlStyleFamily nFamily,
        sal_Int32 nElement,
        const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList );

    virtual SvXMLStyleContext *CreateDefaultStyleStyleChildContext(
        XmlStyleFamily nFamily, sal_Int32 nElement,
        const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList );

    virtual bool InsertStyleFamily( XmlStyleFamily nFamily ) const;

public:

    typedef std::vector<SvXMLStyleContext*> StyleIndex;

    SvXMLStylesContext( SvXMLImport& rImport,
        bool bAutomatic = false );

    virtual ~SvXMLStylesContext() override;

    // Create child element.
    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
        sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override final;

    // This allows to add an SvXMLStyleContext to this context from extern
    void AddStyle(SvXMLStyleContext& rNew);

    const SvXMLStyleContext *FindStyleChildContext(
                                      XmlStyleFamily nFamily,
                                      const OUString& rName,
                                      bool bCreateIndex = false ) const;
    std::pair<StyleIndex::const_iterator, StyleIndex::const_iterator>
                             FindStyleChildContextByDisplayNamePrefix(
                                      XmlStyleFamily nFamily,
                                      const OUString& rNamePrefix) const;
    static XmlStyleFamily GetFamily( std::u16string_view rFamily );
    virtual SvXMLImportPropertyMapper* GetImportPropertyMapper(
                        XmlStyleFamily nFamily ) const;

    virtual css::uno::Reference< css::container::XNameContainer >
        GetStylesContainer( XmlStyleFamily nFamily ) const;
    virtual OUString GetServiceName( XmlStyleFamily nFamily ) const;

    css::uno::Reference< css::style::XAutoStyleFamily >
        GetAutoStyles( XmlStyleFamily nFamily ) const;
    void CopyAutoStylesToDoc();
    void CopyStylesToDoc( bool bOverwrite, bool bFinish = true );
    void FinishStyles( bool bOverwrite );

    // This method must be called to release the references to all styles
    // that are stored in the context.
    void dispose();
    bool IsAutomaticStyle() const;
};

#endif // INCLUDED_XMLOFF_XMLSTYLE_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
