/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Serge Bazanski <q3k@symbioticeda.com>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#ifndef LINESHADER_H
#define LINESHADER_H

#include <QOpenGLBuffer>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLWidget>
#include <array>

#include "log.h"
#include "nextpnr.h"

NEXTPNR_NAMESPACE_BEGIN

// Vertex2DPOD is a structure of X, Y coordinates that can be passed to OpenGL
// directly.
NPNR_PACKED_STRUCT(struct Vertex2DPOD {
    GLfloat x;
    GLfloat y;

    Vertex2DPOD(GLfloat X, GLfloat Y) : x(X), y(Y) {}
});

// LineShaderData is a built set of vertices that can be rendered by the
// LineShader.
// Each LineShaderData can have its' own color and thickness.
struct LineShaderData
{
    std::vector<Vertex2DPOD> vertices;
    std::vector<Vertex2DPOD> normals;
    std::vector<GLfloat> miters;
    std::vector<GLuint> indices;

    int last_render = 0;

    void clear(void)
    {
        vertices.clear();
        normals.clear();
        miters.clear();
        indices.clear();
    }
};

// PolyLine is a set of segments defined by points, that can be built to a
// ShaderLine for GPU rendering.
class PolyLine
{
  private:
    std::vector<QVector2D> points_;
    bool closed_;

    void buildPoint(LineShaderData *building, const QVector2D *prev, const QVector2D *cur, const QVector2D *next) const;

  public:
    // Create an empty PolyLine.
    PolyLine(bool closed = false) : closed_(closed) {}

    // Create a non-closed polyline consisting of one segment.
    PolyLine(float x0, float y0, float x1, float y1) : closed_(false)
    {
        point(x0, y0);
        point(x1, y1);
    }

    // Add a point to the PolyLine.
    void point(float x, float y) { points_.push_back(QVector2D(x, y)); }

    // Built PolyLine to shader data.
    void build(LineShaderData &target) const;

    // Set whether line is closed (ie. a loop).
    void setClosed(bool closed) { closed_ = closed; }
};

// LineShader is an OpenGL shader program that renders LineShaderData on the
// GPU.
// The LineShader expects two vertices per line point. It will push those
// vertices along the given normal * miter. This is used to 'stretch' the line
// to be as wide as the given thickness. The normal and miter are calculated
// by the PolyLine build method in order to construct a constant thickness line
// with miter edge joints.
//
//        +------+------+
//
//               |
//        PolyLine.build()
//               |
//               V
//
//        ^      ^      ^
//        |      |      |    <--- normal vectors (x2, pointing in the same
//       +/+----+/+----+/+        direction)
//
//               |
//         vertex shader
//               |
//               V
//
//        +------+------+ ^ by normal * miter * thickness/2
//        |      |      |
//        +------+------+ V by normal * miter * thickness/2
//
//                         (miter is flipped for every second vertex generated)
class LineShader
{
  private:
    QObject *parent_;
    QOpenGLShaderProgram *program_;

    // GL attribute locations.
    struct
    {
        // original position of line vertex
        GLuint position;
        // normal by which vertex should be translated
        GLuint normal;
        // scalar defining:
        // - how stretched the normal vector should be to
        //   compensate for bends
        // - which way the normal should be applied (+1 for one vertex, -1
        //   for the other)
        GLuint miter;
    } attributes_;

    // GL buffers
    struct Buffers
    {
        QOpenGLBuffer position;
        QOpenGLBuffer normal;
        QOpenGLBuffer miter;
        QOpenGLBuffer index;
        QOpenGLVertexArrayObject vao;
        int indices = 0;

        int last_vbo_update = 0;
    };
    std::array<Buffers, GraphicElement::STYLE_MAX> buffers_;

    // GL uniform locations.
    struct
    {
        // combines m/v/p matrix to apply
        GLuint projection;
        // desired thickness of line
        GLuint thickness;
        // color of line
        GLuint color;
    } uniforms_;

  public:
    LineShader(QObject *parent) : parent_(parent), program_(nullptr) {}

    static constexpr const char *vertexShaderSource_ =
            "#version 150\n"
            "in highp vec2  position;\n"
            "in highp vec2  normal;\n"
            "in highp float miter;\n"
            "uniform   highp float thickness;\n"
            "uniform   highp mat4  projection;\n"
            "void main() {\n"
            "   vec2 p = position.xy + vec2(normal * thickness/2.0 / miter);\n"
            "   gl_Position = projection * vec4(p, 0.0, 1.0);\n"
            "}\n";

    static constexpr const char *fragmentShaderSource_ = "#version 150\n"
                                                         "uniform   lowp  vec4  color;\n"
                                                         "out vec4 Out_Color;\n"
                                                         "void main() {\n"
                                                         "   Out_Color = color;\n"
                                                         "}\n";

    // Must be called on initialization.
    bool compile(void);

    void update_vbos(enum GraphicElement::style_t style, const LineShaderData &line);

    // Render a LineShaderData with a given M/V/P transformation.
    void draw(enum GraphicElement::style_t style, const QColor &color, float thickness, const QMatrix4x4 &projection);
};

NEXTPNR_NAMESPACE_END

#endif
