/*
 * (C) Copyright 1996-2016 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

/*!
    \file SVGDriver.h
    \brief Definition of SVGDriver.
    \author Meteorological Visualisation Section, ECMWF

    Started: Fri Oct 26 20:58:21 2007
*/

#ifndef _SVGDriver_H
#define _SVGDriver_H

#include "BaseDriver.h"
#include "SVGDriverAttributes.h"
#include "XmlNode.h"

namespace magics {

/*! \class SVGDriver
    \brief This driver produces output for SVG
    \ingroup drivers

    This driver provides output in the SVG format:

    \sa http://www.w3.org/Graphics/SVG/
*/
class SVGDriver : public BaseDriver, public SVGDriverAttributes {
public:
    SVGDriver();
    ~SVGDriver() override;
    void open() override;
    void close() override;

    /*!
      \brief sets a new XML node
    */
    void set(const XmlNode& node) override {
        XmlNode basic = node;
        basic.name("driver");
        BaseDriver::set(basic);
        basic.name("svg");
        SVGDriverAttributes::set(basic);
    }

    /*!
      \brief sets a new map
    */
    void set(const map<string, string>& map) override {
        BaseDriver::set(map);
        SVGDriverAttributes::set(map);
    }

private:
    MAGICS_NO_EXPORT void startPage() const override;
    MAGICS_NO_EXPORT void endPage() const override;
    MAGICS_NO_EXPORT void project(const Layout& lay) const override;
    MAGICS_NO_EXPORT void unproject() const override;
    MAGICS_NO_EXPORT void redisplay(const StaticLayer& layer) const override;
    MAGICS_NO_EXPORT void redisplay(const StepLayer& layer) const override;
    MAGICS_NO_EXPORT void redisplay(const NoDataLayer& layer) const override;
    MAGICS_NO_EXPORT string buildLayerName(const Layer* layer, string type) const;
    MAGICS_NO_EXPORT void newLayer() const override;
    MAGICS_NO_EXPORT void closeLayer() const override;
    //	MAGICS_NO_EXPORT void renderInteractiveBegin(const InteractiveBegin&) const  override ;
    //	MAGICS_NO_EXPORT void renderInteractiveEnd(const InteractiveEnd&) const  override ;

    MAGICS_NO_EXPORT void setNewLineWidth(const MFloat) const override;
    MAGICS_NO_EXPORT void setNewColour(const Colour& col) const override;
    MAGICS_NO_EXPORT void setLineParameters(const LineStyle style, const MFloat w) const override;
    //	MAGICS_NO_EXPORT void printLine(const Polyline &line) const;

    //	MAGICS_NO_EXPORT void redisplay(const Polyline& line) const;
    MAGICS_NO_EXPORT void renderPolyline(const int, MFloat*, MFloat*) const override;
    MAGICS_NO_EXPORT void renderPolyline2(const int n, MFloat* x, MFloat* y) const override;
    MAGICS_NO_EXPORT void renderSimplePolygon(const int, MFloat*, MFloat*) const override;
    MAGICS_NO_EXPORT void renderSimplePolygon(const Polyline& line) const override;
    MAGICS_NO_EXPORT void renderText(const Text& text) const override;
    MAGICS_NO_EXPORT bool renderPixmap(const Pixmap&) const override;
    MAGICS_NO_EXPORT void renderSymbols(const Symbol& symbol) const override;
    MAGICS_NO_EXPORT bool renderCellArray(const Image& obj) const override;
    MAGICS_NO_EXPORT void renderImage(const ImportObject& obj) const override;
    MAGICS_NO_EXPORT void circle(const MFloat x, const MFloat y, const MFloat r, const int) const override;

    //! Method to print string about this class on to a stream of type ostream (virtual).
    MAGICS_NO_EXPORT void print(ostream&) const override;
    MAGICS_NO_EXPORT void debugOutput(const string& s) const override;

    MAGICS_NO_EXPORT MFloat setY(const MFloat y) const override { return -y; }
    MAGICS_NO_EXPORT MFloat setSymbolY(const MFloat y) const override { return -y; }
    MAGICS_NO_EXPORT MFloat setAngleY(const MFloat y) const override { return y; }
    MAGICS_NO_EXPORT MFloat setFlagY(const MFloat y) const override { return -y; }
    MAGICS_NO_EXPORT double getRatio() const { return getYDeviceLength() / getXDeviceLength(); }

    MAGICS_NO_EXPORT void openGroup(string g) const;
    MAGICS_NO_EXPORT void closeGroup() const;
    MAGICS_NO_EXPORT bool isGroup() const { return groupString_.empty(); }

    mutable ofstream pFile_;    //!< Output stream to file.
    mutable string tmp_pFile_;  //!< Tmp to hold output stream to file.
    mutable string groupString_;
    mutable int group_counter_;
    //	mutable bool		showCoordinates_;
    mutable bool inkscape_;
    //	mutable bool		interactive_;
    //	mutable unsigned short	interactiveCounter_;

    mutable std::vector<string> layers_;
    mutable stringarray svg_output_resource_list_;

    //! Copy constructor - No copy allowed
    SVGDriver(const SVGDriver&);
    //! Overloaded << operator to copy - No copy allowed
    SVGDriver& operator=(const SVGDriver&);

    // -- Friends
    //! Overloaded << operator to call print().
    friend ostream& operator<<(ostream& s, const SVGDriver& p) {
        p.print(s);
        return s;
    }
};

}  // namespace magics
#endif
