/*
 * Infected Engine
 *
 * Copyright (c) 2013-2014 David Simmerson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#ifndef _Flag_hpp
#define _Flag_hpp

    // **************************************************************
    // our flag system, this is used in all sorts of places; and is
    // essentialy a god when it comes to bitsetting; (well not really)
    // but it is simplistic, which is important.
    // this class is virtualized for a reason, we want to inherit this
    // class and have direct access to the flag manipulation.
    class Flag
    {
        public:
            Flag() {
                highestFlag = 0;
            }
            virtual ~Flag() { }
        private:
            std::map<int, bool>mFlag;
            int        highestFlag;
        public:
            void cleanFlags ( void ) {
                std::map<int, bool>::iterator iter, iter_next;
                for ( iter = mFlag.begin(); iter != mFlag.end(); iter = iter_next ) {
                    int x = iter->first;
                    bool s = iter->second;
                    iter_next = ++iter;
                    // strip out our old flag.
                    if ( !s ) { mFlag.erase ( x ); }
                }
            }
  
            bool hasFlag ( int flag ) {
                std::map<int, bool>::iterator iter, iter_next;
                for ( iter = mFlag.begin(); iter != mFlag.end(); iter = iter_next ) {
                    int x = iter->first;
                    bool s = iter->second;
                    iter_next = ++iter;
                    // could be true or false?
                    if ( x == flag ) {
                        return s;
                    }
                }
                return false;
            }
  
            // toggle the flag on/off!
            void toggleFlag ( int flag ) {
                std::map<int, bool>::iterator iter, iter_next;
                // set the flag
                if ( !hasFlag ( flag ) ) {
                    mFlag[flag] = true;
                    if ( flag > highestFlag )
                    { highestFlag = flag; }
                    return;
                }
                // get rid of the flag
                for ( iter = mFlag.begin(); iter != mFlag.end(); iter = iter_next ) {
                    int x = iter->first;
                    iter_next = ++iter;
                    if ( x == flag ) {
                        mFlag.erase ( x );
                        break;
                    }
                }
            }
  
            void setFlag ( int flag, bool value ) {
                // removing the flag!
                if ( hasFlag ( flag ) && !value ) {
                    std::map<int, bool>::iterator iter, iter_next;
                    for ( iter = mFlag.begin(); iter != mFlag.end(); iter = iter_next ) {
                        int x = iter->first;
                        iter_next = ++iter;
                        if ( x == flag ) {
                            mFlag.erase ( x );
                            break;
                        }
                    }
                    return;
                }
                // we don't have it, so we don't set it (save memory)
                if ( !value ) { return; }
                mFlag[flag] = value;
                if ( flag > highestFlag )
                { highestFlag = flag; }
            }
  
            std::string flagToString ( void ) {
                std::string retStr ( "" );
                int x = 0;
                while ( x <= highestFlag ) {
                    char buf[10];
                    
                    // -- February 15 2014
                    // -- in a std::map, when you call mFlag[x]
                    // -- if the iterator to the location of x doesn't exist
                    // -- it creates it with a default value, we later clean this
                    // -- up and remove that pointer to the empty data.
                    // -- savings are minimal, but worth it.
                    // --          David Simmerson (Omega)
                    snprintf ( buf, 10, "%d", mFlag[x] );
                    retStr.append ( buf );
                    // increment towards our final destination
                    x++;
                }
                // this cleans up our 'other' flags. ones that are 0 instead of 1
                // with std::map's when you access them, it creates the default value
                // so using mFlag[x], if it wasn't set before, it sets it.  cleanFlags
                // strips all those that are set to 0; minimal memory saved, but long-term
                // it could be a healthy life saver.
                cleanFlags();
                return retStr;
            }
  
            void stringToFlag ( const std::string &str ) {
                size_t x = 0;
                while ( str[x] != '\0' ) {
                    if ( x > str.length() )
                    { break; }
                    // only if we are set to 1 shall we add it :)
                    if ( str[x] == '1' ) {
                        mFlag[x] = true;
                        highestFlag = x;
                    }
                    // increment!
                    x++;
                }
            }
    };
#endif