//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
// Original author: David Cosgrove (AstraZeneca)
// 19th June 2014
//

#include "MolDraw2DQt.h"

#include <QPainter>
#include <QString>

using namespace boost;
using namespace std;

namespace RDKit {

  // ****************************************************************************
  MolDraw2DQt::MolDraw2DQt( int width , int height , QPainter &qp ) :
  MolDraw2D( width , height ) , qp_( qp ) {

  }

  // ****************************************************************************
  void MolDraw2DQt::setColour( const DrawColour &col ) {

    MolDraw2D::setColour( col );
    QColor this_col( int( 255.0 * col.get<0>() ) , int( 255.0 * col.get<1>() ) ,
                     int( 255.0 * col.get<2>() ) );

    QPen pen( this_col );
    pen.setJoinStyle( Qt::RoundJoin );
    pen.setColor( this_col );
    qp_.setPen( pen );

    QBrush brush( this_col );
    brush.setStyle( Qt::SolidPattern );
    qp_.setBrush( brush );

  }

  // ****************************************************************************
  void MolDraw2DQt::drawLine( const Point2D &cds1 ,
                              const Point2D &cds2 ) {

    Point2D c1 = getDrawCoords( cds1 );
    Point2D c2 = getDrawCoords( cds2 );

    const DashPattern &dashes=dash();
    QPen pen=qp_.pen();
    if(dashes.size()){
      QVector<qreal> dd;
      for(unsigned int di=0;di<dashes.size();++di) dd << dashes[di];
      pen.setDashPattern(dd);
    } else {
      pen.setStyle(Qt::SolidLine);
    }
    pen.setWidth(lineWidth());
    qp_.setPen(pen);
    qp_.drawLine( QPointF( c1.x , c1.y ) , QPointF( c2.x , c2.y ) );

  }

  // ****************************************************************************
  // draw the char, with the bottom left hand corner at cds
  void MolDraw2DQt::drawChar( char c , const Point2D &cds ) {

    QRectF br = qp_.boundingRect( 0 , 0 , 100 , 100 , Qt::AlignLeft | Qt::AlignBottom ,
                                  QString( c ) );
    qp_.drawText( QRectF( cds.x , cds.y , br.width() , br.height() ) ,
                  Qt::AlignLeft | Qt::AlignBottom , QString( c ) , &br );

  }

  // ****************************************************************************
  void MolDraw2DQt::drawPolygon( const vector<Point2D > &cds ) {
    PRECONDITION(cds.size()>=3,"must have at least three points");
#ifdef NOTYET
    QBrush brush( "Black" );
    brush.setStyle( Qt::SolidPattern );
    DrawColour cc = colour();
    brush.setColor( QColor( 255.0 * cc.get<0>() , 255.0 * cc.get<1>() , 255.0 * cc.get<2>() ) );
#endif

    qp_.save();
    QBrush brush=qp_.brush();
    if(fillPolys())
      brush.setStyle(Qt::SolidPattern);
    else 
      brush.setStyle(Qt::NoBrush);
    qp_.setBrush( brush );

    QPointF points[cds.size()];
    for(unsigned int i=0;i<cds.size();++i){
      Point2D lc = getDrawCoords( cds[i] );
      points[i] = QPointF( lc.x, lc.y );
    }
    qp_.drawConvexPolygon( points , cds.size() );
    qp_.restore();
  }

  // ****************************************************************************
  void MolDraw2DQt::clearDrawing() {

    qp_.setBackground( QBrush( "white" ) );
    qp_.fillRect( 0 , 0 , width() , height() , QColor( "white") );

  }

  // ****************************************************************************
  void MolDraw2DQt::setFontSize( double new_size ) {

    MolDraw2D::setFontSize( new_size );
    double font_size_in_points = fontSize() * scale();
#ifdef NOTYET
    cout << "initial font size in points : " << qp_.font().pointSizeF() << endl;
    cout << "font_size_in_points : " << font_size_in_points << endl;
#endif
    QFont font( qp_.font() );
    font.setPointSizeF( font_size_in_points );
    qp_.setFont( font );

    while( 1 ) {
      double old_font_size_in_points = font_size_in_points;
      double font_size_in_points = fontSize() * scale();
      if( fabs( font_size_in_points - old_font_size_in_points ) < 0.1 ) {
        break;
      }
      QFont font( qp_.font() );
      font.setPointSizeF( font_size_in_points );
      qp_.setFont( font );
      calculateScale();
    }

  }

  // ****************************************************************************
  // using the current scale, work out the size of the label in molecule coordinates
  void MolDraw2DQt::getStringSize( const string &label , double &label_width ,
                                   double &label_height ) const {

    label_width = 0.0;
    label_height = 0.0;

    int draw_mode = 0; // 0 for normal, 1 for superscript, 2 for subscript
    QString next_char( " " );
    bool had_a_super = false;

    for( int i = 0 , is = label.length() ; i < is ; ++i ) {

      // setStringDrawMode moves i along to the end of any <sub> or <sup>
      // markup
      if( '<' == label[i] && setStringDrawMode( label , draw_mode , i ) ) {
        continue;
      }

      next_char[0] = label[i];
      QRectF br = qp_.boundingRect( 0 , 0 , 100 , 100 ,
                                    Qt::AlignBottom | Qt::AlignLeft , next_char );
      label_height = br.height() / scale();
      double char_width = br.width() / scale();
      if( 2 == draw_mode ) {
        char_width *= 0.5;
      } else if( 1 == draw_mode ) {
        char_width *= 0.5;
        had_a_super = true;
      }
      label_width += char_width;

    }

    // subscript keeps its bottom in line with the bottom of the bit chars,
    // superscript goes above the original char top by a quarter
    if( had_a_super ) {
      label_height *= 1.25;
    }

  }

} // EO namespace RDKit
