#include "cctrlgraph.h"
#include <QBrush>
#include <QColor>
#include <QTransform>
#include <QStylePainter>
#include <QStaticText>
#include <QPainterPath>
#include "cmpoint.h"
#include "m_math.h"
#include "cshapelogic.h"
#include "ccoordpolar.h"
#include "def_global_gui.h"
CCtrlGraph::CCtrlGraph(QWidget *parent) :
    CMWidget(parent)
{
    m_sName=tr("Graph");

    m_iMargin=65;

    m_bCapture=false;
    m_iPenWidth=0;
    m_bEnableZoom=true;
    m_bEnbleDrawText=false;
    m_bISOTROPIC=true;

    m_iZeroPos=CENTER_POS;
    setFocusPolicy(Qt::StrongFocus);

    m_bInit=false;
    m_BKColor=QRgb(0xececec);
}

void CCtrlGraph::init_rectWindow()
{
    m_rectWindow.m_width=m_dRangeXMax;
    m_rectWindow.m_height=m_dRangeYMax;
    adjust_rectWindow(true );
}

CCtrlGraph::~CCtrlGraph()
{
}

void CCtrlGraph::MInit()
{
    if(!m_bEnbleDrawText)
    {
        m_iMargin=0;
    }
    init_rectWindow();
}

void CCtrlGraph::MTimeFresh()
{

}

void CCtrlGraph::MFresh()
{
    refreshPixmap();
}

void CCtrlGraph::MApply()
{

}
static int32_t text_offset=15;
void CCtrlGraph::draw_Coord(QPainter &painter)
{
    for(QList<double>::iterator ii=lUnitsX.begin();ii!=lUnitsX.end();ii++)
    {
        m_dCurUnitX=*ii;
        if(m_rectWindow.m_width>m_dCurUnitX)break;
    }
    for(QList<double>::iterator ii=lUnitsY.begin();ii!=lUnitsY.end();ii++)
    {
        m_dCurUnitY=*ii;
        if(m_rectWindow.m_height>m_dCurUnitY)break;
    }
    QRectF rectView=get_rectClip();
    double dstepViewX=rectView.width()/m_rectWindow.m_width*m_dCurUnitX;

    double dstepViewY=rectView.height()/m_rectWindow.m_height*m_dCurUnitY;

    QBrush bhtext(palette().windowText().color());
    QBrush bhline(palette().mid().color());
    painter.setPen(QPen(bhtext,0));
    double dpos=int32_t(m_rectWindow.bottomleft().tX/m_dCurUnitX)*m_dCurUnitX;

    if(dpos<m_rectWindow.bottomleft().tX) dpos+=m_dCurUnitX;
    for(;dpos<m_rectWindow.bottomright().tX;dpos+=m_dCurUnitX)
    {
        painter.setPen(QPen(bhline,0,Qt::DashLine));
        QPointF pttopw,ptbottomw;
        QPointF pttopv,ptbottomv;
        pttopw=QPointF(dpos,m_rectWindow.topleft().tY);
        ptbottomw=QPointF(dpos,m_rectWindow.bottomright().tY);
        pttopv=m_trans_LP2DP.map(pttopw);
        ptbottomv=m_trans_LP2DP.map(ptbottomw);
        painter.drawLine(pttopv,ptbottomv);
        if(m_bEnbleDrawText)
        {
            QRectF rectText(QPointF(ptbottomv.x()-dstepViewX/2,ptbottomv.y()),
                            QPointF(ptbottomv.x()+dstepViewX/2,ptbottomv.y()+m_iMargin));
            rectText.adjust(0,text_offset,0,text_offset);
            painter.setPen(QPen(bhtext,0));
            painter.drawText(rectText,Qt::AlignHCenter|Qt::AlignTop,QString("%1").arg(dpos));
        }
    }

    dpos=int32_t(m_rectWindow.bottomleft().tY/m_dCurUnitY)*m_dCurUnitY;
    if(dpos<m_rectWindow.bottomleft().tY)dpos+=m_dCurUnitY;
    for(;dpos<m_rectWindow.topright().tY;dpos+=m_dCurUnitY)
    {
        painter.setPen(QPen(bhline,0,Qt::DashLine));
        QPointF ptleftw,ptrightw;
        QPointF ptleftv,ptrightv;
        ptleftw=QPointF(m_rectWindow.topleft().tX,dpos);
        ptrightw=QPointF(m_rectWindow.bottomright().tX,dpos);
        ptleftv=m_trans_LP2DP.map(ptleftw);
        ptrightv=m_trans_LP2DP.map(ptrightw);
        painter.drawLine(ptleftv,ptrightv);
        if(m_bEnbleDrawText)
        {
            QRectF rectText(QPointF(ptleftv.x()-m_iMargin,ptleftv.y()-dstepViewY/2),
                            QPointF(ptleftv.x(),ptleftv.y()+dstepViewY/2));
            rectText.adjust(-text_offset,0,-text_offset,0);
            painter.setPen(QPen(bhtext,0));
            painter.drawText(rectText,Qt::AlignVCenter|Qt::AlignRight,
                             QString("%1").arg(dpos));
        }
    }
    if(!m_bEnbleDrawText) return;
    //单位和坐标系指示线
    rectView.adjust(0,0,-1,-1);
    painter.setPen(QPen(bhtext,0));
    painter.drawRect(rectView);

    painter.drawStaticText(text_offset,text_offset,
                           QStaticText(tr("unit:(%1/%2)").
                                       arg(m_strUnitY).
                                       arg(m_strUnitX)));

    QPointF bottomleft= rect().bottomLeft();

    bottomleft.rx()+=text_offset;
    bottomleft.ry()-=text_offset;

    painter.drawLine(bottomleft.x(),bottomleft.y(),
                     bottomleft.x()+m_iMargin,bottomleft.y());
    QPainterPath path(QPointF(bottomleft.x()+m_iMargin,bottomleft.y()));
    path.lineTo(QPointF(bottomleft.x()+m_iMargin-text_offset,bottomleft.y()+text_offset/2));
    path.lineTo(QPointF(bottomleft.x()+m_iMargin-text_offset,bottomleft.y()-text_offset/2));
    path.lineTo(QPointF(bottomleft.x()+m_iMargin,bottomleft.y()));
    painter.fillPath(path,bhtext);

    painter.drawText(bottomleft.x()+m_iMargin+text_offset,
                     bottomleft.y()+ text_offset/2,
                     "X");
    painter.drawLine(bottomleft.x(),bottomleft.y(),
                     bottomleft.x(),bottomleft.y()-m_iMargin);

    path=QPainterPath(QPointF(bottomleft.x(),bottomleft.y()-m_iMargin));
    path.lineTo(QPointF(bottomleft.x()+text_offset/2,bottomleft.y()-m_iMargin+text_offset));
    path.lineTo(QPointF(bottomleft.x()-text_offset/2,bottomleft.y()-m_iMargin+text_offset));
    path.lineTo(QPointF(bottomleft.x(),bottomleft.y()-m_iMargin));

    painter.fillPath(path,bhtext);
    painter.drawText(bottomleft.x()- text_offset/2,
                     bottomleft.y()-m_iMargin-text_offset,
                     "Y");
}

void CCtrlGraph::updaterubberBandRect()
{
    QRect rect_normalized= m_rubberBandRect.normalized();
    update(rect_normalized.left(),rect_normalized.top(),rect_normalized.width(),1);
    update(rect_normalized.left(),rect_normalized.top(),1,rect_normalized.height());
    update(rect_normalized.left(),rect_normalized.bottom(),rect_normalized.width(),1);
    update(rect_normalized.right(),rect_normalized.top(),1,rect_normalized.height());
}

void CCtrlGraph::refreshPixmap(bool bupdate)
{
    m_Pixmap=QPixmap(size());
    m_Pixmap.fill(m_BKColor);
    QPainter painter(&m_Pixmap);
    painter.initFrom(this);
    if(!painter.isActive())return;
    adjust_rectWindow(false);
    draw_Coord(painter);
    painter.setPen(Qt::lightGray);
    QRectF rect1=rect();
    rect1.adjust(0.5,0.5,-0.5,-0.5);
    painter.drawRect(rect1);
    QRectF rectView=get_rectClip();
    painter.setClipRect(rectView);
    if(bupdate)
    {
        update();
    }
}

void CCtrlGraph::CalcuTransfrom()
{
    QRectF rectView=get_rectClip();
    QPolygonF one,two;
    one.push_back(QPointF(m_rectWindow.topleft().tX,m_rectWindow.topleft().tY));
    one.push_back(QPointF(m_rectWindow.bottomright().tX,m_rectWindow.bottomright().tY));
    one.push_back(QPointF(m_rectWindow.topright().tX,m_rectWindow.topright().tY));
    one.push_back(QPointF(m_rectWindow.bottomleft().tX,m_rectWindow.bottomleft().tY));

    two.push_back(QPointF(rectView.topLeft().x(),rectView.topLeft().y()));
    two.push_back(QPointF(rectView.bottomRight().x(),rectView.bottomRight().y()));
    two.push_back(QPointF(rectView.topRight().x(),rectView.topRight().y()));
    two.push_back(QPointF(rectView.bottomLeft().x(),rectView.bottomLeft().y()));
    bool bsuccess= QTransform::quadToQuad(one,two,m_trans_LP2DP);
    Q_ASSERT(bsuccess);
    //    bsuccess= QTransform::quadToQuad(two,one,m_trans_DP2LP);
    //    Q_ASSERT(bsuccess);
    m_trans_DP2LP=m_trans_LP2DP.inverted(&bsuccess);
    Q_ASSERT(bsuccess);
}
void CCtrlGraph::paintEvent(QPaintEvent *pEvent)
{
    UNUSED(pEvent);
    QStylePainter painter(this);
    painter.drawPixmap(0,0,m_Pixmap);

    if(m_bCapture)
    {
        QRect rect_normalized= m_rubberBandRect.normalized();
        rect_normalized.adjust(0,0,-1,-1);
        painter.setPen(palette().mid().color());
        painter.drawRect(rect_normalized);
    }

}

void CCtrlGraph::showEvent(QShowEvent *pEvent)
{
    UNUSED(pEvent);
    if(!m_bInit)
    {
        m_bInit=true;
        ZoomFit();
    }
}

void CCtrlGraph::mousePressEvent(QMouseEvent *pEvent)
{
    m_bCapture=false;
    if(pEvent->button()==Qt::LeftButton)
    {
        if(m_bEnableZoom)
        {
            QRectF rectView=get_rectClip();
            QPointF posEvent=pEvent->pos();
            if(rectView.contains(posEvent))
            {
                m_rubberBandRect.setTopLeft(pEvent->pos());
                m_rubberBandRect.setBottomRight(pEvent->pos());
                m_bCapture=true;
            }
        }
    }
    else if(pEvent->button()==Qt::RightButton)
    {
        ZoomFit();
    }
}

void CCtrlGraph::mouseReleaseEvent(QMouseEvent *pEvent)
{
    UNUSED(pEvent);
    if(pEvent->button()==Qt::LeftButton)
    {
        if(m_bCapture)
        {
            m_bCapture=false;
            QRect rect_normalized= m_rubberBandRect.normalized();
            if((rect_normalized.width()>4&&rect_normalized.height()>4))
            {
                QPointF topleft=m_trans_DP2LP.map(rect_normalized.topLeft());
                QPointF bottomright=m_trans_DP2LP.map(rect_normalized.bottomRight());

                double curRangeX= fabs(double(topleft.x()-bottomright.x()));
                double curRangeY= fabs(double(topleft.y()-bottomright.y()));
                if(curRangeX>m_dRangeXMin&&curRangeY>m_dRangeYMin)
                {
                    QPointF center= m_trans_DP2LP.map(rect_normalized.center());
                    m_rectWindow.m_center=CMPointd(center.x(),center.y());
                    m_rectWindow.m_width=curRangeX;
                    m_rectWindow.m_height=curRangeY;
                }
            }
            refreshPixmap();
        }
    }
}

void CCtrlGraph::mouseMoveEvent(QMouseEvent *pEvent)
{
    if(m_bCapture )
    {
        updaterubberBandRect();
        m_rubberBandRect.setBottomRight(pEvent->pos());
        updaterubberBandRect();
    }
}

void CCtrlGraph::wheelEvent(QWheelEvent *pEvent)
{
    int numDegrees=pEvent->delta()/8;
    int numticks=numDegrees/15;
    m_rectWindow.m_width-=numticks*m_dCurUnitX/10.0;
    m_rectWindow.m_height-=numticks*m_dCurUnitY/10.0;

    //   QPoint center= m_trans_DP2LP.map(pEvent->pos());
    //   m_rectWindow.m_center=CMPointd(center.x(),center.y());
    refreshPixmap();
}

void CCtrlGraph::resizeEvent(QResizeEvent *)
{
//    adjust_rectWindow(false);
//    refreshPixmap();

    ZoomFit();
}

void CCtrlGraph::ZoomIn()
{
    if(!m_bEnableZoom) return;
    m_rectWindow.m_width*=2;
    m_rectWindow.m_height*=2;
    refreshPixmap();
}

void CCtrlGraph::ZoomOut()
{
    if(!m_bEnableZoom) return;
    m_rectWindow.m_width/=2;
    m_rectWindow.m_height/=2;
    refreshPixmap();
}

void CCtrlGraph::ZoomFit()
{
    init_rectWindow();
    refreshPixmap();
}

QRectF CCtrlGraph::get_rectClip()
{
    QRect cliprect=rect();
    cliprect.adjust(m_iMargin,m_iMargin,-m_iMargin,-m_iMargin);
    return cliprect;
}

void CCtrlGraph::adjust_rectWindow(bool bresetZero)
{
    QRectF rectView=get_rectClip();
    double dviewwidth=rectView.width();
    double dviewheight=rectView.height();
    double dwindowwidth=m_rectWindow.m_width;
    double dwindowheight=m_rectWindow.m_height;
    dwindowwidth= min(dwindowwidth,m_dRangeXMax);
    dwindowwidth= max(dwindowwidth,m_dRangeXMin);

    dwindowheight= min(dwindowheight,m_dRangeYMax);
    dwindowheight= max(dwindowheight,m_dRangeYMin);

    if(m_bISOTROPIC)
    {

        double dscale=max(dwindowwidth/dviewwidth,
                          dwindowheight/dviewheight);

        dwindowwidth=dviewwidth*dscale;
        dwindowheight=dviewheight*dscale;
    }

    m_rectWindow.m_width=dwindowwidth;
    m_rectWindow.m_height=dwindowheight;

    if(bresetZero)
    {
        switch(m_iZeroPos)
        {
        case CENTER_POS:
            m_rectWindow.m_center.tX=0;
            m_rectWindow.m_center.tY=0;
            break;
        case LEFT_BOTTOM:
            m_rectWindow.m_center.tX=dwindowwidth/2;
            m_rectWindow.m_center.tY=dwindowheight/2;
            break;
        case LEFT_CENTER:
            m_rectWindow.m_center.tX=dwindowwidth/2;
            m_rectWindow.m_center.tY=0;
            break;
        case LEFT_TOP:
            m_rectWindow.m_center.tX=dwindowwidth/2;
            m_rectWindow.m_center.tY=-dwindowheight/2;
            break;
        case BOTTOM_CENTER:
            m_rectWindow.m_center.tX=0;
            m_rectWindow.m_center.tY=dwindowheight/2;
            break;
        case BOTTOM_RIGHT:
            m_rectWindow.m_center.tX=-dwindowwidth/2;
            m_rectWindow.m_center.tY=dwindowheight/2;
            break;
        default:
            Q_ASSERT(0);
        }
    }
    CalcuTransfrom();
}
