/*
Copyright 2020 Siemens Digital Industries Software
==================================================
Copyright 2020
Siemens Product Lifecycle Management Software Inc.
All Rights Reserved.
==================================================
Copyright 2020 Siemens Digital Industries Software

This header contains the solution variant creation ITK declaration and its supporting structures.
THe details are explained in appropriate structure parameters.
*/

#ifndef SMC0PSMCFGSUPPORT_SOLUTION_VARIANT_ITK_H
#define SMC0PSMCFGSUPPORT_SOLUTION_VARIANT_ITK_H

#include <unidefs.h>
#include <map>
#include <vector>
#include <set>
#include <base_utils/DateTime.hxx>
#include <metaframework/BusinessObjectRef.hxx>
#include <metaframework/BusinessObject.hxx>
#include <Smc0psmcfgsupport/libsmc0psmcfgsupport_exports.h>


#ifdef __cplusplus
extern "C" {
#endif

    namespace Teamcenter
    {
        namespace PSM
        {
            namespace SolutionVariant
            {
                typedef std::map< tag_t, tag_t > ExpandedBOMLine; /**< Map of generic bomline to SV bomline 
                                                                   <br/>This map represents the map of expanded configured bomlines and its
                                                                   equivalent SV bomlines*/

                typedef std::map< std::string, std::string > StringMap;
                typedef std::map< std::string, std::vector< std::string > > StringVectorMap;
                typedef std::map< std::string, BusinessObjectRef< Teamcenter::BusinessObject > > svTagMap;
                typedef std::map< std::string, std::vector< BusinessObjectRef< Teamcenter::BusinessObject > > > TagVectorMap;
                typedef std::map< std::string, int > IntMap;
                typedef std::map< std::string, std::vector< int > > IntVectorMap;
                typedef std::map< std::string, double > DoubleMap;
                typedef std::map< std::string, std::vector< double > > DoubleVectorMap;
                typedef std::map< std::string, float > FloatMap;
                typedef std::map< std::string, std::vector< float > > FloatVectorMap;
                typedef std::map< std::string, Teamcenter::DateTime > DateMap;
                typedef std::map< std::string, std::vector< Teamcenter::DateTime > > DateVectorMap;
                typedef std::map< std::string, bool > BoolMap;
                typedef std::map< std::string, std::vector< bool > > BoolVectorMap;

                struct SMC0PSMCFGSUPPORT_API CreateSVInputProp
                {
                    // the below Maps for which the property and its values are populated correspond to the 
                    // Business Object name (m_boName)
                    std::string m_boName;                                                           /**<  Business Object Name */ // for e,g "Design Revision"
                    StringMap m_stringProps;                                                        /**<  Map of String to String - Property Name to its corresponding string Value >
                                                                                                         <br/> for exmaple m_stringProps[ "item_revision_id" ] = "B" */
                    StringVectorMap m_stringArrayProps;                                             /**<  Property Name to its corresponding list of string values >*/
                    DoubleMap m_doubleProps;                                                        /**<  Map of String to double - Property Name to its corresponding double value > */
                    DoubleVectorMap m_doubleArrayProps;                                             /**<  Property Name to its corresponding list of double values >*/
                    FloatMap m_floatProps;                                                          /**<  Map of String to float - Property Name to its corresponding float value > */
                    FloatVectorMap m_floatArrayProps;                                               /**<  Property Name to its corresponding list of float values >*/
                    IntMap m_intProps;                                                              /**<  Map of String to int - Property Name to its corresponding integer value > */
                    IntVectorMap m_intArrayProps;                                                   /**<  Property Name to its corresponding list of integer values >*/
                    BoolMap m_boolProps;                                                            /**<  Map of String to bool - Property Name to its corresponding bool value > */
                    BoolVectorMap m_boolArrayProps;                                                 /**<  Property Name to its corresponding list of bool values >*/
                    DateMap m_dateProps;                                                            /**<  Map of String to date - Property Name to its corresponding date value > */
                    DateVectorMap m_dateArrayProps;                                                 /**<  Property Name to its corresponding list of date values >*/
                    svTagMap m_tagProps;                                                            /**<  Map of String to tag_t - Property Name to its corresponding tag value(typereference value) > */
                    TagVectorMap m_tagArrayProps;                                                   /**<  Property Name to its corresponding list of tag values >*/
                    std::map< std::string, std::vector< CreateSVInputProp > > m_compoundSVItemProp; /**<  for example 
                                                                                                    <br/> Teamcenter::PSM::SolutionVariant::CreateSVInputProp revProp.
                                                                                                    <br/> std::vector<Teamcenter::PSM::SolutionVariant::CreateSVInputProp> revCompProps.
                                                                                                    <br/> revProp.m_boName = "ItemRevision".
                                                                                                    <br/> revProp.m_stringProps[ "item_revision_id" ] = "B".
                                                                                                    <br/> revCompProps.push_back( revProp ).
                                                                                                    <br/> solVarCreateObjInfo.m_createSVInputProp.m_compoundSVItemProp["revision"] = revCompProps.
                                                                                                    <br/> currently only "revision" is defined in the code */
                    CreateSVInputProp() : m_boName(""), m_stringProps(), m_stringArrayProps(), m_doubleProps(), m_doubleArrayProps(), m_floatProps(), m_floatArrayProps(), m_intProps(), m_intArrayProps(),
                        m_boolProps(), m_boolArrayProps(), m_dateProps(), m_dateArrayProps(), m_tagProps(), m_tagArrayProps(), m_compoundSVItemProp()
                    {
                    }
                    CreateSVInputProp(std::string boName) : m_boName(boName), m_stringProps(), m_stringArrayProps(), m_doubleProps(), m_doubleArrayProps(), m_floatProps(), m_floatArrayProps(), m_intProps(), m_intArrayProps(),
                        m_boolProps(), m_boolArrayProps(), m_dateProps(), m_dateArrayProps(), m_tagProps(), m_tagArrayProps(), m_compoundSVItemProp() {}
                };
                struct SMC0PSMCFGSUPPORT_API SolVarCreateInfo
                {
                    CreateSVInputProp m_createSVInputProp;      /**<  structure for mapped properties */
                    tag_t m_genericBomLine;                     /**<  Generic bomline */
                    int m_solVarCategory;                       /**<  solution variant category */
                    tag_t m_subsetVariantRule;                  /**<  system calculated variant rule - internally used 
                                                                <br/> top (svr_top->color=red & size=small)
                                                                <br/> ----sub1
                                                                <br/> ----sub2 (svr_asm->size=small)
                                                                <br/> ------------sub3
                                                                <br/> ------------sub4
                                                                <br/>    svr_top is variant rule set on top.
                                                                <br/>    svr_asm is subset variant rule set on sub2.
                                                                <br/>    subsetVariantRule created internally 
                                                                <br/>    (svr_asm->size=small) referring above structure*/
                    tag_t m_newSolVarItemRevision;              /**<   corresponding solution variant item revision - internally used */
                    bool m_isSolVarIsExist;                     /**<   for Reuse category  - true if found existing sol variant else false - internally used */
                    int m_errorcode;                            /**<   indicates failed error code */
                    SolVarCreateInfo() :m_createSVInputProp(), m_genericBomLine(NULLTAG), m_solVarCategory(-1), m_subsetVariantRule(NULLTAG), m_newSolVarItemRevision(NULLTAG), m_isSolVarIsExist(false), m_errorcode(0)
                    {
                    }
                    SolVarCreateInfo(CreateSVInputProp createSVInputProp, tag_t genericBomLine, int solVarCategory, tag_t newSolVarItemRevision)
                        :m_createSVInputProp(createSVInputProp), m_genericBomLine(genericBomLine), m_solVarCategory(solVarCategory), m_subsetVariantRule(NULLTAG),
                        m_newSolVarItemRevision(newSolVarItemRevision), m_isSolVarIsExist(false), m_errorcode(0) {}
                };

                struct SMC0PSMCFGSUPPORT_API MultilevelSolVarCreateInfo
                {
                    SolVarCreateInfo m_solVarCreateInfo;        /**<  Input structure */
                    tag_t m_mappedSVBomLine;                    /**<  The mapped SV bomline */
                    int bomLinelevel;                           /**<  The corresponding bomline level */
                    int m_errorcode;                            /**<  indicates failed error code */
                    MultilevelSolVarCreateInfo() :m_solVarCreateInfo(), m_mappedSVBomLine(NULLTAG), m_errorcode(0)
                    {
                    }
                    MultilevelSolVarCreateInfo(SolVarCreateInfo solVarCreateInfo, tag_t mappedSVBomLine, int level) :
                        m_solVarCreateInfo(solVarCreateInfo), m_mappedSVBomLine(mappedSVBomLine), bomLinelevel(level), m_errorcode(0) {}
                };

                // Output structure of solution variant created.
                struct  SMC0PSMCFGSUPPORT_API MultilevelSolVarCreateOutput
                {
                    tag_t m_genericBOMLine;                    /**<  The generic bomline which was sent as Input . */
                    tag_t m_newVariantBOMLine;                 /**<  The corresponding solution variant bomline . */
                    std::string status;                        /**<  The status information of the solution variant created. 
                                                               <br/> For example, 
                                                               <br/> Created new Solution Variant "\%1\$" for generic assembly "\%2\$"*/
                    int bomLinelevel;                          /**<  The corresponding bom level expanded */
                    int m_errorcode;                           /**<  Indicates failed error code*/
                    MultilevelSolVarCreateOutput() :m_genericBOMLine(0), m_newVariantBOMLine(0), m_errorcode(0)
                    {
                    }
                };

                struct  SMC0PSMCFGSUPPORT_API MultilevelSolVarCreateResponse
                {
                    std::vector < MultilevelSolVarCreateOutput > m_multilevelSolVarCreateOutputList; /**< List of SV output details */
                    std::map< tag_t, tag_t > m_expandedBOMLines;                                     /**< Map of generic bomline to SV bomline 
                                                                                                     <br/>This map represents the map of expanded configured bomlines and its
                                                                                                     <br/>equivalent SV bomlines */
                    MultilevelSolVarCreateResponse()
                    {
                    }
                };
            }
        }
    }

   /**
    Create solution variant based on the inputs.
    More details are given against each parameter of the function SMC0_solution_variants_creation.

    @returns
    <ul>
    <li>#ITK_ok on success.
    <li>#TYPE_unknown_type if the input gvToSVType has the mapped Solution Variant BO type to be "UnknownType" for e,g ("Item", "UnknownType").
    <li>#SMC0PSMCFGSUPPORT_blocked_single_level_reuse_sv_creation if IIK is asked to create single level SV with solution category as "Reuse".
    <li>#SMC0PSMCFGSUPPORT_invalid_variant_rule_error if pcaVariantRule is NULLTAG.
    <li>#SMC0PSMCFGSUPPORT_invalid_or_incomplete_variant_rule if pcaVariantRule is invalid or incomplete.
    <li>#BOM_internal_error if due to some reason the SV creation is rolled back.
    </ul>
    ---------------------------------------
    How to construct the input for the ITK
    --------------------------------------
    @code
       for example, the below code snippet is for all levels.
        BOM_create_window(&bomWindow);
        tag_t topLine = NULLTAG;
        BOM_set_window_top_line(bomWindow, NULLTAG, itemRev, NULLTAG, &topLine);
        CreateSVInputProp prop(type); // type is mapped SV BO Type
        for example, if gvToSVType is ("Item", "Design"), SV BO Type is "Design".
        SolVarCreateInfo solVarCreInfo(prop, 
                                      topLine, // bomline input
                                      svCategory, // can be one of the solution variant categories
                                      NULLTAG //solution var item revision - will be created internally.);
        MultilevelSolVarCreateInfo multilevelSolVarCreateInfo( solVarCreInfo, //  solVarCreInfo, see above
                                                               NULLTAG, // m_mappedSVBomLine, for multilevel true this is generated internally
                                                               level); // corresponding bomline level.
        std::vector< MultilevelSolVarCreateInfo > multilevelSolVarCreateInfoList;
        multilevelSolVarCreateInfoList.push_back(multilevelSolVarCreateInfo);
        std::map< std::string, int > preferencesMap;
        preferencesMap.insert(std::pair<std::string, int>("DryRun", 0));
        std::map < std::string, std::string > gvToSVType;
        // call ITK
        SMC0_solution_variants_creation(multilevelSolVarCreateInfoList, 
                                        m_svrRuleTag//saved variant rule tag , 
                                        preferencesMap, 
                                         NULLTAG //revRule, 
                                         true//multilevel, 
                                         gvToSVType, 
                                        multilevelSolVarCreateResponse);


        // Since solution variant bomlines are returned  via output response. The caller should ensure that corresponding BOM window
        // are closed after processing bom lines. The caller should also ensure that window corresponding to Generic bomline is also
        // closed.

        // if multilevel is false, and if the caller wants to do level by level processing for creating solution variants
        // then the caller should make output of the previous level as the input of the next level.
        // for example m_expandedBOMLines contains the map of generic bomline to SV bomline
        // the caller should populate MultilevelSolVarCreateInfo from m_expandedBOMLines of the previous level and call SMC0_solution_variants_creation ITK again
        //  for example,
        // SolVarCreateInfo solVarCreInfo(prop, 
                                        m_expandedBOMLines->first, // bomline input
                                        svCategory, // can be one of the solution variant categories
                                        NULLTAG //solution var item revision - will be created internally.);
        // MultilevelSolVarCreateInfo multilevelSolVarCreateInfo( solVarCreInfo, //  solVarCreInfo, see above
                                                               m_expandedBOMLines->second, // m_mappedSVBomLine
                                                               level); // corresponding bomline level.
        // std::vector< MultilevelSolVarCreateInfo > multilevelSolVarCreateInfoList;
        // multilevelSolVarCreateInfoList.push_back(multilevelSolVarCreateInfo);
        // for the rest, please see How to construct the input for the ITK
    @endcode
    */
    
    SMC0PSMCFGSUPPORT_API extern int SMC0_solution_variants_creation(
            std::vector< Teamcenter::PSM::SolutionVariant::MultilevelSolVarCreateInfo > &multilevelSolVarCreateInfoList, /**< (I) Input details of Solution Variant to be created */
            const tag_t savedVariantRule,                                                                                /**< (I) Saved Variant Rule  */
            const std::map< std::string, int > &preferencesMap,                                                          /**< (I) The following preferences are used.
                                                                                                                         <br/>DryRun, allLevel, RollbackOnError, StopOnError
                                                                                                                         <br/>Usage: preferencesMap["DryRun"] = 1
                                                                                                                         <br/>Usage: preferencesMap["RollbackOnError"] = 1
                                                                                                                         <br/>"RollbackOnError" rolls back to the original state on error.
                                                                                                                         <br/>Usage: preferencesMap["StopOnError"] = 1
                                                                                                                         <br/>"StopOnError" stops further processing on error and returns 
                                                                                                                         <br/>appropriate error code.
                                                                                                                         <br/>Usage: preferencesMap["allLevel"] = 0
                                                                                                                         <br/>if multilevel is true and  preferencesMap["allLevel"] = 0
                                                                                                                         <br/>solution variant is created till first level.
                                                                                                                         */
            const tag_t revRule,                                                                                         /**< (I) Input Revision Rule tag */
            bool multilevel,                                                                                             /**< (I) multilevel (true or false)
                                                                                                                         <br/> If multilevel is true then solution variants are created for all levels.
                                                                                                                         <br/> If multilevel is false then solution variants are created for single level.
                                                                                                                         <br/> if multilevel is true and  preferencesMap["allLevel"] = 0
                                                                                                                          solution variant is created till first level.*/
            const std::map < std::string, std::string > &gvToSVType,                                                     /**< (I) This map represents the mapping of BO type of generic and solution variant bomline
                                                                                                                         <br/>for e,g  gvToSVType.insert( pair< std::string, std::string>( "Item", "Design" ) )
                                                                                                                         <br/>"Item" is Generic Variant BO type and "Design" is solution variant BO type. */
            Teamcenter::PSM::SolutionVariant::MultilevelSolVarCreateResponse & multilevelSolVarCreateResponse);          /** < (O) Ouput response of Solution Variants created */

#ifdef __cplusplus
}
#endif

/** @} */

#include <Smc0psmcfgsupport/libsmc0psmcfgsupport_undef.h>
#endif