/***************************************************************************
        Copyright (C) 2002-2026 Kentaro Kitagawa
		                   kitag@issp.u-tokyo.ac.jp
		
		This program is free software; you can redistribute it and/or
		modify it under the terms of the GNU Library General Public
		License as published by the Free Software Foundation; either
		version 2 of the License, or (at your option) any later version.
		
		You should have received a copy of the GNU Library General 
		Public License and a list of authors along with this program; 
		see the files COPYING and AUTHORS.
***************************************************************************/
//---------------------------------------------------------------------------

#ifndef analyzerH
#define analyzerH

#include "xnode.h"
#include "xitemnode.h"
#include "xlistnode.h"
#include "support.h"
#include "xnodeconnector.h"
#include "driver.h"

class DECLSPEC_KAME XScalarEntry : public XNode {
public:
	XScalarEntry(const char *name, bool runtime, const shared_ptr<XDriver> &driver,
				 const char *format = 0L);

	//A condition for determining a trigger of storing.
	//0: never
	//negative: allways
	//positive: when the difference from old value exceeds 'Delta'.
	const shared_ptr<XDoubleNode> &delta() const {return m_delta;}
	//if false, one line should not include this.
	const shared_ptr<XBoolNode> &store() const {return m_store;}

	const shared_ptr<XDoubleNode> &value() const {return m_value;}
	const shared_ptr<XDoubleNode> &storedValue() const {return m_storedValue;}
  
	void storeValue(Transaction &tr);

	shared_ptr<XDriver> driver() const {return m_driver.lock();}
  
	virtual XString getLabel() const;
  
	void value(Transaction &tr, double val);

	struct Payload : public XNode::Payload {
		Payload() : m_bTriggered(false) {}
		bool isTriggered() const {return m_bTriggered;}
	private:
		friend class XScalarEntry;
		bool m_bTriggered;
	};
protected:
private:
	const weak_ptr<XDriver> m_driver;
 
	const shared_ptr<XDoubleNode> m_delta;
	const shared_ptr<XBoolNode> m_store;

	const shared_ptr<XDoubleNode> m_value;
	const shared_ptr<XDoubleNode> m_storedValue;
};

class XDriverList;

class DECLSPEC_KAME XScalarEntryList : public XAliasListNode<XScalarEntry> {
public:
	XScalarEntryList(const char *name, bool runtime) : XAliasListNode<XScalarEntry>(name, runtime) {}
};

class Ui_FrmGraph;
class QMainWindow;
typedef QForm<QWidget, Ui_FrmGraph> FrmGraph;
class XGraph;
class XXYPlot;

class DECLSPEC_KAME XValChart : public XNode {
public:
	XValChart(const char *name, bool runtime, const shared_ptr<XScalarEntry> &entry);
	void showChart();
	const shared_ptr<XScalarEntry> &entry() const {return m_entry;}
private:
    shared_ptr<Listener> m_lsnOnRecord;
	//callback from Driver
    void onVisualization(const Snapshot &shot, bool afterRecorded, XDriver *driver);

	const shared_ptr<XScalarEntry> m_entry;
	shared_ptr<XGraph> m_graph;
	qshared_ptr<FrmGraph> m_graphForm;
	shared_ptr<XXYPlot> m_chart;
};

class DECLSPEC_KAME XChartList : public XAliasListNode<XValChart> {
public:
	XChartList(const char *name, bool runtime, const shared_ptr<XScalarEntryList> &entries);
private:
    shared_ptr<Listener> m_lsnOnCatchEntry;
    shared_ptr<Listener> m_lsnOnReleaseEntry;
    void onCatchEntry(const Snapshot &shot, const XListNodeBase::Payload::CatchEvent &e);
    void onReleaseEntry(const Snapshot &shot, const XListNodeBase::Payload::ReleaseEvent &e);

	const shared_ptr<XScalarEntryList> m_entries;
};

class DECLSPEC_KAME XValGraph : public XNode {
public:
	XValGraph(const char *name, bool runtime,
		Transaction &tr_entries, const shared_ptr<XScalarEntryList> &entries);

	void showGraph();
	void clearAllPoints();
    FrmGraph *graphForm();

	typedef XItemNode<XScalarEntryList, XScalarEntry> tAxis;
  
	const shared_ptr<tAxis> &axisX() const {return m_axisX;}
	const shared_ptr<tAxis> &axisY1() const {return m_axisY1;}
	const shared_ptr<tAxis> &axisZ() const {return m_axisZ;}

	struct Payload : public XNode::Payload {
	private:
		friend class XValGraph;
		shared_ptr<XGraph> m_graph;
		shared_ptr<XXYPlot> m_livePlot, m_storePlot;
	};
protected:
private:
	qshared_ptr<FrmGraph> m_graphForm;

	shared_ptr<tAxis> m_axisX, m_axisY1, m_axisZ;
    shared_ptr<Listener> m_lsnAxisChanged;
	void onAxisChanged(const Snapshot &shot, XValueNodeBase *node);

    shared_ptr<Listener> m_lsnOnVisualization;
    shared_ptr<Listener> m_lsnStoreChanged;
	void onVisualization(const Snapshot &shot, bool afterRecorded, XDriver *driver);
	void onStoreChanged(const Snapshot &shot, XValueNodeBase *node);

	weak_ptr<XScalarEntryList> m_entries;
};

class DECLSPEC_KAME XGraphList : public XCustomTypeListNode<XValGraph> {
public:
	XGraphList(const char *name, bool runtime, const shared_ptr<XScalarEntryList> &entries);

    virtual shared_ptr<XNode> createByTypename(const XString &, const XString& name);
	const shared_ptr<XScalarEntryList> &entries() const {return m_entries;}
private:
	const shared_ptr<XScalarEntryList> m_entries;
};

class XCalibrationCurveList;
class XCalibrationCurve;
class XMeasure;

//! A calibrated scalar value derived from another entry via a calibration curve.
//! Acts as a proper XDriver: records on each source driver record, fires onVisualization.
class DECLSPEC_KAME XCalibratedEntry : public XDriver {
public:
    XCalibratedEntry(const char *name, bool runtime,
        Transaction &tr_meas, const shared_ptr<XMeasure> &meas,
        const shared_ptr<XScalarEntryList> &entries,
        const shared_ptr<XCalibrationCurveList> &curves);
    virtual ~XCalibratedEntry();

    typedef XItemNode<XScalarEntryList, XScalarEntry> tSource;
    typedef XItemNode<XCalibrationCurveList, XCalibrationCurve> tCurve;
    const shared_ptr<tSource>      &source() const { return m_source; }
    const shared_ptr<tCurve>       &curve()  const { return m_curve; }
    const shared_ptr<XScalarEntry> &entry()  const { return m_entry; }

    virtual void showForms() override {}
protected:
    virtual void visualize(const Snapshot &) override {}
private:
    shared_ptr<tSource>      m_source;
    shared_ptr<tCurve>       m_curve;
    shared_ptr<XScalarEntry> m_entry;  // own scalar entry, always in XScalarEntryList
    const weak_ptr<XScalarEntryList>      m_entries;
    shared_ptr<Listener> m_lsnSelectionChanged;
    shared_ptr<Listener> m_lsnOnRecord;  // connects to current source driver's onRecord
    void onSelectionChanged(const Snapshot &, XValueNodeBase *);
    void onSourceDriverRecord(const Snapshot &shot, XDriver *driver);
};

//! List of calibrated entries
class DECLSPEC_KAME XCalibratedEntryList : public XCustomTypeListNode<XCalibratedEntry> {
public:
    XCalibratedEntryList(const char *name, bool runtime,
        const shared_ptr<XScalarEntryList> &entries,
        const shared_ptr<XCalibrationCurveList> &curves,
        const shared_ptr<XMeasure> &meas);
    shared_ptr<XNode> createByTypename(const XString &, const XString &name) override;
    shared_ptr<XCalibrationCurveList> curves()  const { return m_curves.lock(); }
    shared_ptr<XScalarEntryList> entries()  const { return m_entries.lock(); }
private:
    const weak_ptr<XScalarEntryList>      m_entries;
    const weak_ptr<XCalibrationCurveList> m_curves;
    const weak_ptr<XMeasure>               m_measure;
};
//---------------------------------------------------------------------------
#endif

