/*
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃                                                                                                 ┃
┃         Class Name(s): SmithChart, GraphicsScene                                                ┃
┃             File Name: smithbasics.h                                                            ┃
┃                Author: Michael Krämer                                                           ┃
┃                 Email: Michael@dk8pp.de                                                         ┃
┃                  Date: 04.03.2025                                                               ┃
┃                  Tool: Qt                                                                       ┃
┃                Device: Windows/Linux                                                            ┃
┃               Version: 0.1                                                                      ┃
┃        Program status: still testing                                                            ┃
┃                                                                                                 ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃                                                                                                 ┃
┃  Purpose: Include file for smithbasics.cpp                                                      ┃
┃                                                                                                 ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃                                                                                                 ┃
┃  © Copyright 2025 Michael Krämer, DK8PP                                                         ┃
┃                                                                                                 ┃
┃  This program is free software: you can redistribute it and/or modify it under the terms of     ┃
┃  the GNU Lesser General Public License as published by the Free Software Foundation, either     ┃
┃  version 3 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 Lesser General Public License for more details.                                    ┃
┃                                                                                                 ┃
┃  You should have received a copy of the GNU Lesser General Public License along with this       ┃
┃  program.   If not, see <http://www.gnu.org/licenses/>.                                         ┃
┃                                                                                                 ┃
┃  ============================================================================================   ┃
┃                                                                                                 ┃
┃  Dieses Programm ist Freie Software: Sie können es unter den Bedingungen der GNU Lesser         ┃
┃  General Public License, wie von der Free Software Foundation, Version 3 der Lizenz oder        ┃
┃  (nach Ihrer Wahl) jeder neueren veröffentlichten Version, weiter verteilen und/oder            ┃
┃  modifizieren.                                                                                  ┃
┃                                                                                                 ┃
┃  Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein wird, jedoch OHNE   ┃
┃  JEDE GEWÄHR,; sogar ohne die implizite Gewähr der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN        ┃
┃  BESTIMMTEN ZWECK. Siehe die GNU Lesser General Public License für weitere Einzelheiten.        ┃
┃                                                                                                 ┃
┃  Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit diesem Programm      ┃
┃  erhalten haben. Wenn nicht, siehe <https://www.gnu.org/licenses/>.                             ┃
┃                                                                                                 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

ToDo:
━━━━━

*/

#ifndef SMITHBASICS_H
#define SMITHBASICS_H

#include <QWidget>
#include <QSettings>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsSceneWheelEvent>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsEllipseItem>
#include <QDoubleSpinBox>
#include <QTimer>
#include <QPainter>
#include <QPaintDevice>
#include <QPainterPath>
#include <QQuickWidget>
#include <QGraphicsSimpleTextItem>
#include <QMenu>
#include <QFont>
#include <QPointF>
#include <complex>
//#include "commondefs.h"

/*
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│       Defines                                                                                   │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
*/
typedef std::complex<double> complex_dbl ;
constexpr complex_dbl complex_1 = {1.0, 0.0} ;  /* complex constant: 1+i0 */
constexpr double Z0R = 50.0 ;                   /* real part of default reference impedance */

namespace Ui {
  class SmithBasics ;
}

class GraphicsScene ;

/*
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│       global variables                                                                          │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
*/
/* Note: Using an untransformed view: one unit on the scene is represented by one pixel on the screen. */
constexpr double SDIAM = 250.0 ;                /* diameter of smith chart in number of pixels */
constexpr double SMARGIN = 10.0 ;               /* additional margin around chart */
constexpr int ICOUNT = 6 ;                      /* number of impedance and admittance lines */
constexpr int NODE_COUNT = 50 ;                 /* number of nodes for match lines */
constexpr int SMITH_NODE_COUNT = 180 ;          /* number of nodes for circle in smith chart */

/*
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│       markerItem                                                                                │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
*/
class markerItem : public QObject, public QGraphicsPathItem
{
    Q_OBJECT
public:
   GraphicsScene *scene ;

protected:
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override ;
//    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override ;

//signals:
private:
} ;

class MyTextItem : public QGraphicsSimpleTextItem {
    public:
        void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0 )
        {
            painter->setBrush( Qt::red );
            painter->drawRect( boundingRect() );
            QGraphicsSimpleTextItem::paint( painter, option, widget );
        }
} ;

/*
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│       GraphicsScene                                                                             │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
*/
class GraphicsScene : public QGraphicsScene
{
   Q_OBJECT

public:
   GraphicsScene() = default ;
   void DrawSmithchart() ;
   void DrawGamma() ;
   void getPos(QPointF *point, complex_dbl *impedance) ;
   QGraphicsSimpleTextItem *print(const QString& text, QFont *font, QBrush *brush, qreal posx, qreal posy) ;
   void PrintInfo(const QString& text, int location) ;
   void ClearInfo(int location) ;
   void updateMarker(complex_dbl *gamma) const ;
   void addSceneMarker(bool moveable) ;
   void addSceneSwrItems(int count) ;
   void updateSceneSWR(double *swr, int count) ;
   void AddParallelImp(complex_dbl *imp, complex_dbl *parImp) ;
   void AddSerialImp(complex_dbl *imp, complex_dbl *serImp) ;
   void RemoveImp() ;
   void RemoveImp(int num) ;
   void set_opacity(qreal op) ;
   void markerDragged(QPointF pos) ;
   void setGamma(complex_dbl gamma) ;
   void updateSmithLabels(qreal newZ0R) ;
   std::array <qreal, SMITH_NODE_COUNT> resistances ;

signals:
   void NewGamma(complex_dbl gamma) ;

protected:

private:
   complex_dbl complex_1 = {1.0, 0.0} ; /* complex constant: 1+i0 */
   complex_dbl z0 = {Z0R, 0.0} ;        /* complex reference impedance */
   QPainterPath marker;
   QPainterPath gridline ;
   markerItem *markeritem = nullptr ;
   QList <QGraphicsEllipseItem *> swr_list ;
   QList <QGraphicsPathItem *> match_list ;
   std::array <QGraphicsSimpleTextItem *, 4> infoitem = {nullptr, nullptr, nullptr, nullptr} ;
   QList <QGraphicsItem *> smithitems ;
   QGraphicsItemGroup *smithgroup = nullptr ;
   QList <QGraphicsItem *> gammaitems ;
   QGraphicsItemGroup *gammagroup = nullptr ;
   QGraphicsLineItem *markerline ;
   QList <QGraphicsSimpleTextItem *> smithlabelitems ;
   QList <QGraphicsSimpleTextItem *> gammalabelitems ;
} ;

/*
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│       SmithChart                                                                                │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
*/
class SmithBasics
{
public:
   SmithBasics() ;
   ~SmithBasics() ;
   void init_graphics_view(QGraphicsView *qgv) ;
   void DrawSmithchart() ;
   void DrawGamma() ;
   QRectF sceneRect() ;
   void clear() ; /* Removes and deletes (!) all items from the scene */
   void AddParallelImp(complex_dbl *imp, complex_dbl *parImp) ;
   void AddSerialImp(complex_dbl *imp, complex_dbl *serImp) ;
   void PrintInfo(const QString& text, int location) ;
   void ClearInfo(int location) ;
   void RemoveImp() ;
   void RemoveImp(int num) ;
   void updateMarker(complex_dbl *gamma) ;
   bool isOpen() ;
   void setOpen() ;
   void setClosed() ;
   void updateSWR(double *swr, int count) ;
   void addSwrItems(int count) ;
   void addMarker(bool moveable) ;
   void set_opacity(qreal op) ;
   GraphicsScene *scene = nullptr ;
   void setGamma(complex_dbl gamma) ;
   void newZ0(qreal newZ0R) ;
   int get_rescount() ;
   qreal get_res(int index) ;

private:
   QGraphicsView *graphics_view = nullptr ;
   bool is_open = false ;

};

#endif // SMITHBASICS_H
