/* 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/.
 * 
 * utils.cpp
 *
 *      Author: pgess <v.melnychenko@xreate.org>
 */

#ifndef UTILS_H
#define UTILS_H

#include "jeayeson/jeayeson.hpp"

//TODO use type mark to mark dirty/mutable members

/*
template<class T>
struct DdesctructableClass<T> {

}
*/
/*
template<class OriginalType>
struct TagUpdatable{
    TagUpdatable(const OriginalType& source)
            : __source(source)
    {}

    TagUpdatable() = delete;

    const OriginalType& __source;
};


struct Updatable;

template <class Tag, class OT>
struct TagsDictionary
{};

template<class OT>
struct TagsDictionary<Updatable, OT>
{
    typedef TagUpdatable<OT> TagName;
};

template<class Tag, class OT>
struct awareOf
{
    awareOf(OT& dest)
        : __dest(dest)
    {}

    awareOf<Tag, OT>&
        operator= (const typename TagsDictionary<Tag, OT>::TagName& source)
    {
        __dest = source.__source;
    }

private:
    OT& __dest;
};

template<class Tag<OT>>
const OT&
awareOf(const Tag<OT>& holder)
{
    return std::forward<OT>(holder.__source);
}

 */

namespace xreate {
    template<class Tag, class Source>
    struct AddTag {

        explicit
        AddTag(const Source &src)
                : __src(src) { }

        explicit
        AddTag(Source &&src)
                : __src(std::move(src)) { }

        operator const Source&() const{
            return __src;
        }

        const Source& get() const{
            return __src;
        }

        const Source*
        operator->() const {
        	return &__src;
        }

    private:
        Source __src;
    };

    struct Expand_t{};
    template<class Source>
    using Expanded = AddTag<Expand_t, Source>;
    


 //DEBT move to resources compiler. https://github.com/markusfisch/cpprc
    class Config {
    private: 
      json_map __storage;
      static Config __self;
      Config();
      
    public: 
       static std::string get(std::string key) {
        return __self.__storage.get_for_path<json_value>(key).get<std::string>();
      }
    };
    
    /**
     *  Decorators support
     */
    template<class DecoratorTag>
    struct DecoratorsDict{
        //typedef ConcreteDecoratorForTag result;
    };
    
    template<class DecoratorTag>
    struct Decorators{
        typedef typename DecoratorsDict<DecoratorTag>::result Instance;

        template<class Base>
        static Instance* getInterface(Base* obj){
            return dynamic_cast< Instance* > (obj);
        }
    };
}

std::wstring
utf8_to_wstring(const std::string& str);

std::string
wstring_to_utf8(const std::wstring& str);


#define RST  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define KBLU  "\x1B[34m"
#define KMAG  "\x1B[35m"
#define KCYN  "\x1B[36m"
#define KWHT  "\x1B[37m"

#define FRED(x) KRED << x << RST
#define FGRN(x) KGRN <<x << RST
#define FYEL(x) KYEL << x << RST
#define FBLU(x) KBLU << x << RST
#define FMAG(x) KMAG x RST
#define FCYN(x) KCYN x RST
#define FWHT(x) KWHT x RST

#define BOLD(x) "\x1B[1m" x RST
#define UNDL(x) "\x1B[4m" x RST

#endif // UTILS_H
