#ifndef DESCRIBER_H
#define DESCRIBER_H

#ifndef OWN_H
#include "Own.h"
#endif

#ifndef FILE_TEXT_OUTPUT_H
#include "File_text_output.h"
#endif

namespace MM
{

class Describer
{
public:
    class Protocol
    {
    public:
        virtual void    description (Text const & text) =0;
	virtual 	~Protocol () {}
    };

    class Stub : public Protocol
    {
        Stub () {}
    public:
        static Stub & singleton ()
        {
            static Stub instance;
            return instance;
        }
        void description (Text const &) { }
    };

    class Proxy : public Protocol
    {
        Describer    *impl_;
    public:
        explicit Proxy (Describer & impl) : impl_(&impl) { }
        void description (Text const & text)
            {impl_->description (Text("\t") + text);}
    };

    class Impl : public Protocol
    {
        Own <Text_output>       out_;

    public:
        explicit Impl (Text const & name) 
        :   out_(new File_text_output (name)) { }

        void description (Text const & text)
        {
            out_().line (text);
            out_().flush ();
        }
    };

private:
    Protocol       *impl_;
    Own <Protocol>  janitor_;
    bool            on_;

public:
    Describer () : impl_(&Stub::singleton()), on_(true) { }

    void            in  (Describer & next)
    {
        impl_= new Proxy (next);
        janitor_.adopt (impl_);
    }

    bool            is_on () const                      {return on_;}
    //void            off ()                          {impl_= &Stub::singleton();}
    void            set_on (bool on)                  
    {
        on_= on;
    }
    
    void            description (Text const & text) 
    {
        if (on_) 
            impl_->description (text);
    }

    void            write_in_file (Text const & name)
    {
        impl_= new Impl (name);
        janitor_.adopt (impl_);
    }
};

}//MM

#endif //DESCRIBER_H
