/* -*- C++ -*-

  This file is part of ViPEC
  Copyright (C) 1991-2001 Johan Rossouw (jrossouw@alcatel.altech.co.za)

  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.

  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.

  You should have received a copy of the GNU Library General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef SUBCIRCUIT_H
#define SUBCIRCUIT_H

#include <Types.h>
#include <Matrix.h>
#include <DataPoint.h>
#include <Component.h>
#include <CircuitNode.h>

#include <qlist.h>

class QDomElement;
class QTextStream;
class QPainter;

class Schematic
{
public:
  Schematic();
  virtual ~Schematic();
  Schematic& operator=( const Schematic& );

  void setName(const QString& name);
  const QString& getName() const;

  enum SchematicSize { smallSize, mediumSize, largeSize };
  void setSize( SchematicSize size );
  SchematicSize getSize() const;
  uint width() const;
  uint height() const;
  
  void addComponent( Component* component );
  void removeComponent( Component* component );
  Component* findComponentAt( const QPoint& point );
  void findComponentsInsideRect( QList<Component>&, QRect& );
  Component* findTextAt( const QPoint& point );

  void addNode( CircuitNode* node );
  void removeNode( CircuitNode* node );
  CircuitNode* findNodeAt( const QPoint& point );
  void findNodesInsideRect( QList<CircuitNode>&, QRect& );

  void addLine( CircuitLine* line );
  void removeLine( CircuitLine* line );
  CircuitLine* findLineAt( const QPoint& point,
			   bool orthoganalOnly);
  void findLinesInsideRect( QList<CircuitLine>&, QRect& );

  void draw( QPainter* );
  
  //Streaming
  void writeToStream( QTextStream& );
  bool readFromDOM( QDomElement& element );
  bool readLineFromDOM( QDomElement& element );
  
  void removeEmptyNodes();
  void renumberPortNodes();
  void numberAllNodes();
  uint getNumberOfNodes() const;
  uint getNumberOfPorts() const;

  void reset();
  bool isSolved() const;
  void initSweep();
  void sweep(Vector&);

  QList<DataPoint>& getSData();
  QList<DataPoint>& getYData();
  QList<DataPoint>& getZData();
  TComplex getPortImpedance( uint port );
  
private:
  Schematic( const Schematic& );

  int distanceFromLine( const QPoint& point,
			const CircuitLine& line,
			bool orthoganalOnly );

  void findAllConnectedNodes(CircuitNode* node, QList<CircuitNode>& nodeList);

private:
  QString name_;
  SchematicSize size_;
  uint width_;
  uint height_;
  QList<Component> componentList_;
  QList<CircuitNode> nodeList_;
  QList<CircuitLine> lineList_;
  uint portCount_;
  uint maxNodeNr_;

  bool hasChanged_;          //Circuit has changed from last sweep
  bool isSolved_;            //Circuit has valid solved response
  Matrix* yn_;               //Nodal admittance matrix used for solve
  Matrix  zo_;               //Port termination impedance matrix
  QList<DataPoint> zdata_;   //Data after solve
  QList<DataPoint> ydata_;
  QList<DataPoint> sdata_;
};

#endif
