/* 

                          Firewall Builder

                 Copyright (C) 2009 NetCitadel, LLC

  Author:  Vadim Kurland     vadim@fwbuilder.org

  $Id$

  This program is free software which we release under the GNU General Public
  License. You may redistribute and/or modify this program under the terms
  of that license as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This program 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 General Public License for more details.
 
  To get a copy of the GNU General Public License, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#ifndef __BASE_COMPILER_HH__
#define __BASE_COMPILER_HH__

#include "fwbuilder/libfwbuilder-config.h"
#include "fwbuilder/FWException.h"
#include "fwbuilder/Rule.h"

#include "fwcompiler/exceptions.h"

#include <sstream>

namespace fwcompiler {

    class FWCompilerException : public libfwbuilder::FWException {
	libfwbuilder::Rule *rule;
	public:
	FWCompilerException(libfwbuilder::Rule *r,const std::string &err);
	libfwbuilder::Rule *getRule() const { return rule; }
    };

    class BaseCompiler
    {

        std::string level_macro;
        // all errors generated by the compiler
	std::stringstream errors_buffer;
        // a dictionary mapping rule label to the list of errors associated
        // with it.
        std::map<std::string, std::list<std::string> > rule_errors;
        
        // in test mode we trat fatal errors as errors and continue after
        // printing error message
        bool test_mode;
        // this is single-rule-compile mode; compiler is embedded in the GUI
        bool embedded_mode;

        /**
         * assembles standard error message using format similar to
         * the error message format of gcc. Useful to prepare errors
         * and warnings before calling error() or warning() methods
         */
        std::string stdErrorMessage(libfwbuilder::FWObject *fw,
                                    libfwbuilder::FWObject *ruleset,
                                    libfwbuilder::FWObject *rule,
                                    const std::string &errstr);

        std::string setLevel(const std::string &level, const std::string &errstr);

        void printError(const std::string &errstr);

        void message(const std::string &level,
                     libfwbuilder::FWObject *fw,
                     libfwbuilder::FWObject *ruleset,
                     libfwbuilder::FWObject *rule,
                     const std::string &errstr);
        
public:
        typedef enum {FWCOMPILER_SUCCESS, FWCOMPILER_ERROR} termination_status;

protected:
        termination_status status;

public:
        
        virtual void setTestMode() { test_mode = true; }
        bool inTestMode() { return test_mode; }

        virtual void setEmbeddedMode() { embedded_mode = true; }
        bool inEmbeddedMode() { return embedded_mode; }

        termination_status getStatus() { return status; }
        
        /**
         * prints error message and aborts the program. If compiler is
         * in testing mode (flag test_mode==true), then just prints
         * the error message and returns.
         */
	virtual void abort(const std::string &errstr) throw(libfwbuilder::FWException);
	virtual void abort(libfwbuilder::FWObject *fw,
                           libfwbuilder::FWObject *ruleset,
                           libfwbuilder::FWObject *rule,
                           const std::string &errstr) throw(libfwbuilder::FWException);

        /**
         * prints an error message and returns
         */
	virtual void error(const std::string &warnstr);
	virtual void error(libfwbuilder::FWObject *fw,
                           libfwbuilder::FWObject *ruleset,
                           libfwbuilder::FWObject *rule,
                           const std::string &warnstr);

        /**
         * prints warning message
         */
	virtual void warning(const std::string &warnstr);
	virtual void warning(libfwbuilder::FWObject *fw,
                             libfwbuilder::FWObject *ruleset,
                             libfwbuilder::FWObject *rule,
                             const std::string &warnstr);

        /**
         * prints info message. These are only printed to stdout if compiler
         * is not in embedded mode. In embedded mode info messages are ignored.
         */
	virtual void info(const std::string &warnstr);
        
	virtual ~BaseCompiler() {};

	BaseCompiler()
        {
            test_mode = false;
            embedded_mode = false;
            level_macro = "%LEVEL%";
            status = FWCOMPILER_SUCCESS;
        };

	std::string getErrors(const std::string &comment_sep);
	bool haveErrorsAndWarnings();
        void clearErrors();

        std::string getErrorsForRule(libfwbuilder::Rule *rule,
                                     const std::string &comment_sep);

        /**
         * fills a list of strings with regular expressions that match
         * error messages
         */
        static void errorRegExp(std::list<std::string> *err_regexp);

        /**
         * fills a list of strings with regular expressions that match
         * warning messages
         */
        static void warningRegExp(std::list<std::string> *warn_regexp);

    };
}

#endif
