//
//  File:   hzNamering.h
//
//  Legal Notice: This file is part of the HadronZoo C++ Class Library.
//
//  Copyright 1998, 2018 HadronZoo Project (http://www.hadronzoo.com)
//
//  The HadronZoo C++ Class Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
//  as published by the Free Software Foundation, either version 3 of the License, or any later version.
//
//  The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
//  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see
//  http://www.gnu.org/licenses.
//
#ifndef hzNamering_h
#define hzNamering_h
#include "hzTmplSet.h"
#include "hzTmplVect.h"
#include "hzTmplMapM.h"
#include "hzChain.h"
#define NAMEROOT_UNIQUE     0x01    //  All words must be unique
class   hzNamering
{
    //  Category:   Data
    //
    //  A name-ring is a set of one or more name-groups, each of which is considered as set of alternative spellings of the same basic 'root' name. For example,
    //  the name 'Steven' which can be spelt as 'Steven' or 'Stephen', will form a name group with a root of Steven and two members, Steven and Stephen. Such an
    //  arrangement can serve as a useful aide to search facilities.
    //
    //  The hzNamering class impliments a name-ring as a pair of many-to-one maps. The first maps names to name groups while the second does the reverse. Since
    //  this would not ensure uniqueness among name groups, a set is added to ensure no two groups have the same root name.
    class   _name_ring
    {
        //  Internal structure to facilitate soft copy
    public:
        hzSet   <hzString>          m_Groups ;      //  All groups
        hzMapM  <hzString,hzString> m_Roots ;       //  All words. Name-ring members to name-ring roots.
        hzMapM  <hzString,hzString> m_Members ;     //  Back words. Name-ring roots to name-ring members.
        hzLockRWD   m_Lock ;                //  Locking (off by default)
        uint16_t    m_bOpflags ;            //  Allow duplicate words
        uint16_t    m_nNoCopies ;           //  Number of copies
        _name_ring  (void)
        {
            m_nNoCopies = 0 ;
            m_bOpflags = 0 ;
        }
    } ;
    _name_ring*     mx ;        //  Internal instance
public:
    hzNamering  (void) ;
    hzNamering  (hzNamering& op) ;
    ~hzNamering (void) ;
    /*
    **  MT Locking
    */
    hzEcode UseLocking  (const char* name) ;
    hzEcode UseLocking  (const hzString& name) ;
    /*
    **  Clear the name-ring of all keys and elements
    */
    void    Clear   (void) ;
    /*
    **  Search functions
    */
    //  Does the namering have any roots?
    uint32_t    CountRoot       (void)  { return mx ? mx->m_Roots.Count() : 0 ; }
    //  Count number of roots a member belongs to
    uint32_t    RootIncidence   (const hzString& member) const ;
    //  Locate the first root a member belongs to
    hzString        RootLocate      (const hzString& member) const ;
    //  Locate all the roots a member belongs to
    uint32_t    RootLocate      (hzVect<hzString>& results, const hzString& member) const ;
    //  Locate all members of a root
    uint32_t    MemberLocate    (hzVect<hzString>& results, const hzString& root) const ;
    //  Directly obtain roots
    hzString        RootLocate      (uint32_t nIndex) const ;
    /*
    **  Insert functions
    */
    //  Add a new root (root must be unique)
    hzEcode AddRoot     (const hzString& root) ;
    //  Add a member to a root (must be unique within root)
    hzEcode AddMember   (const hzString& root, const hzString& member) ;
    /*
    **  Delete the element matching the key from the map
    */
    //  Delete a root (and all members unless they also belong to other roots)
    hzEcode DelRoot     (const hzString& root) ;
    //  Delete a member from a root
    hzEcode DelMember   (const hzString& root) ;
    /*
    **  Operators and Miscellaneous
    */
    hzNamering& operator=   (hzNamering& op) ;
    void    Report  (std::ofstream& os) const ;
    void    Report  (hzLogger* plog) const ;
} ;
#endif  //  hzNamering_h