#include "graphicsItem/graphicsItemGroup.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
#include <QTimer>

GraphicsItemGroup::GraphicsItemGroup(QGraphicsItem *parent)
    : AbstractShapeType<QGraphicsItemGroup>(parent)
{
    m_type = T_group;

    m_boundingRect = QRectF();
    m_lastBoudingRect = QGraphicsItemGroup::boundingRect();

    //初始化缩放操作用的handle
    m_vecHanle.reserve(H_left);
    for(int i = H_leftTop; i <= H_left; i++)
    {
        ItemControlHandle* pHandle = new ItemControlHandle(this);
        pHandle->setType(T_resize);
        pHandle->setTag(i);
        m_vecHanle.push_back(pHandle);
    }
    for(int i = H_rotate_leftTop; i <= H_rotate_leftBottom; i++)
    {
        ItemControlHandle* pHandle = new ItemControlHandle(this);
        pHandle->setType(T_rotate);
        pHandle->setTag(i);
        m_vecHanle.push_back(pHandle);
    }

    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    setAcceptHoverEvents(true);
}

GraphicsItemGroup::~GraphicsItemGroup()
{
}

QPainterPath GraphicsItemGroup::shape()
{
    QPainterPath path;
    path.addRect(m_boundingRect);
    return path;
}

void GraphicsItemGroup::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    if (option->state & QStyle::State_Selected) //是选中状态,绘制选中框
    {
        int nPenWidth = 1;
        painter->setPen(QPen(QColor(70,70,70), nPenWidth, Qt::DashLine)); //蓝色的外框
        painter->setBrush(Qt::NoBrush);
        painter->drawRect(m_boundingRect_selected);

        //绘制变换原点
        /*QPointF originPoint = transformOriginPoint();
        //qDebug() << "originPoint:" << originPoint << " boundingRect:" << m_boundingRect;
        painter->setBrush(Qt::red);
        painter->drawEllipse(QPointF(0,0), 4, 4);
        painter->setBrush(Qt::blue);
        painter->drawEllipse(originPoint, 4, 4);*/
    }
}

void GraphicsItemGroup::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
    Q_UNUSED(event);
}

QVariant GraphicsItemGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
    if (change == QGraphicsItem::ItemSelectedHasChanged)
    {
        QGraphicsItemGroup *group = dynamic_cast<QGraphicsItemGroup *>(parentItem());
        if(!group)
            setHandleVisible(value.toBool());
        else //在某一组群中，由组群展示是否选中，自身不做展示
        {
            setSelected(false);
            return QVariant::fromValue<bool>(false);
        }
    }
    return QGraphicsItemGroup::itemChange(change, value);
}

void GraphicsItemGroup::syncRotationDataFromParent(const double& data)
{
    /*m_dSyncRotationByParent += data;
    //让角度保持在正负180的区间，也就是上下两个半圈，这样易于象限判断
    if (m_dSyncRotationByParent > 180)
        m_dSyncRotationByParent -= 360;
    if (m_dSyncRotationByParent < -180)
        m_dSyncRotationByParent += 360;
    //同步给子项
    foreach (QGraphicsItem* item, childItems())
    {
        if(qgraphicsitem_cast<ItemControlHandle*>(item))
            continue;

        AbstractShape* shape = qgraphicsitem_cast<AbstractShape*>(item);
        if(shape && shape->getType()==T_group)
        {
            GraphicsItemGroup *group = qgraphicsitem_cast<GraphicsItemGroup *>(item);
            if(group)
                group->syncRotationDataFromParent(data);
        }
        else
        {
            GraphicsBaseItem *baseItem = qgraphicsitem_cast<GraphicsBaseItem*>(item);
            if (baseItem)
                baseItem->syncRotationDataFromParent(data);
        }
    }*/
}

void GraphicsItemGroup::updateCoordinate() //当执行了resie和editShape函数后，boundingRect发生了变换，需要将item的原点(以中心点为原点)校准至boundingRect.center()
{
    if (!parentItem())
    {
        if (m_boundingRect.isNull())
        {
            m_boundingRect = QGraphicsItemGroup::boundingRect();
            m_dWidth = m_boundingRect.width();
            m_dHeight = m_boundingRect.height();
        }

        //因为group包含子item，boundingRect会根据子item自动计算生成，所以不再通过重设boundingRect（中心和原点重合）重合的方式，因为此种方式需要子item做各种同步计算
        //最简单的方式是，每次boundingRect发生变化（缩放）后重新设置变换中心，但是会出现漂移（因为item只存储旋转角度数据，每帧都根据角度进行重绘），具体见开发学习笔记，消除这个漂移即可
        prepareGeometryChange();
        //具体计算
        double dAngle = qDegreesToRadians(rotation());
        QPointF centerPt = m_boundingRect.center();
        QPointF originPt = transformOriginPoint();
        QPointF targetPt = QPointF(0, 0);
        targetPt.setX(originPt.x() + qCos(dAngle)*(centerPt.x() - originPt.x()) - qSin(dAngle)*(centerPt.y() - originPt.y()));
        targetPt.setY(originPt.y() + qSin(dAngle)*(centerPt.x() - originPt.x()) + qCos(dAngle)*(centerPt.y() - originPt.y()));
        QPointF delta = targetPt - centerPt;
        //m_boundingRect.adjust(delta.x(), delta.y(), delta.x(), delta.y());
        setTransformOriginPoint(m_boundingRect.center());
        if(dAngle != 0)
            moveBy(delta.x(), delta.y());

        //QTimer::singleShot(2000,[&](){moveBy(-delta.x(), -delta.y());});

        updateHandles();
    }

    //调用该组内所有item(过滤handle)相关函数
    foreach (QGraphicsItem *item, childItems())
    {
        GraphicsBaseItem *baseItem = qgraphicsitem_cast<GraphicsBaseItem*>(item);
        if (baseItem && !qgraphicsitem_cast<ItemControlHandle*>(baseItem))
        {
            baseItem->updateCoordinate();
        }
    }
    m_lastBoudingRect = m_boundingRect;
}

void GraphicsItemGroup::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint)
{
    switch (nHandle)
    {
    case H_left:
    case H_right:
        dSY = 1; //拖拽的是左点右点，为水平缩放，忽略垂直变化
        break;
    case H_top:
    case H_bottom:
        dSX = 1; //拖拽的是顶点底点，为垂直缩放，忽略水平变化
        break;
    default:
        break;
    }

    QTransform trans;
    //缩放是以图元变换原点为基准，所以每帧都先移动移动到想要的基准点，缩放之后再移回
    trans.translate(basePoint.x(), basePoint.y());
    trans.scale(dSX, dSY);
    trans.translate(-basePoint.x(), -basePoint.y());

    prepareGeometryChange();
    //如果直接将变换应用到item(setTransform(trans))，相当于把坐标进行拉伸，会有明显的拉伸感，所以应用到图形点上效果更好
    //setTransform(trans);
    m_boundingRect = trans.mapRect(m_lastBoudingRect);
    m_dWidth = m_boundingRect.width();
    m_dHeight = m_boundingRect.height();
    updateHandles();

    //调用该组内所有item(过滤handle)相关函数
    foreach (QGraphicsItem *item, childItems())
    {
        GraphicsBaseItem *baseItem = qgraphicsitem_cast<GraphicsBaseItem*>(item);
        if (baseItem && !qgraphicsitem_cast<ItemControlHandle*>(baseItem))
        {
            //qDebug() << "groupBounding: " << m_boundingRect << "  itemBounding:" << baseItem->boundingRect();
           baseItem->resize(nHandle, dSX, dSY, baseItem->mapFromParent(basePoint));
        }
    }
}

void GraphicsItemGroup::createOperationCopy()
{
    m_pOperationCopy = new QGraphicsPathItem(this->shape());
    m_pOperationCopy->setPen(Qt::DashLine);
    m_pOperationCopy->setPos(this->pos());
    m_pOperationCopy->setTransformOriginPoint(this->transformOriginPoint());
    m_pOperationCopy->setTransform(this->transform());
    m_pOperationCopy->setRotation(this->rotation());
    m_pOperationCopy->setScale(this->scale());
    m_pOperationCopy->setZValue(this->zValue());

    QGraphicsScene* scene = this->scene();
    if(scene && m_pOperationCopy)
    {
        scene->addItem(m_pOperationCopy);
        m_movingIniPos = this->pos();
    }
}

void GraphicsItemGroup::removeOperationCopy()
{
    QGraphicsScene* scene = this->scene();
    if(scene && m_pOperationCopy)
    {
        if(this->pos() != m_pOperationCopy->pos())
            this->setPos(m_pOperationCopy->pos()); //本体移动到副本的位置
        if(this->rotation() != m_pOperationCopy->rotation())
        {
            double dAngle = m_pOperationCopy->rotation();
            this->setRotation(dAngle); //本体旋转至副本的角度
            //子item的旋转数据并不会和所在组同步，需要手动同步
            foreach (QGraphicsItem* item, childItems())
            {
                if(qgraphicsitem_cast<ItemControlHandle*>(item))
                    continue;

                // AbstractShape* shape = qgraphicsitem_cast<AbstractShape*>(item);
                // if(shape && shape->getType()==T_group)
                // {
                //     GraphicsItemGroup *group = qgraphicsitem_cast<GraphicsItemGroup *>(item);
                //     if(group)
                //          group->syncRotationDataFromParent(dAngle);
                // }
                // else
                {
                    GraphicsBaseItem *baseItem = qgraphicsitem_cast<GraphicsBaseItem*>(item);
                    if (baseItem)
                        baseItem->syncRotationDataFromParent(dAngle);
                }
            }
        }

        scene->removeItem(m_pOperationCopy);
        delete m_pOperationCopy;
        m_pOperationCopy = nullptr;
    }
}

void GraphicsItemGroup::moveOperationCopy(const QPointF& distance)
{
    if(m_pOperationCopy)
        m_pOperationCopy->setPos(m_movingIniPos + distance);
}

void GraphicsItemGroup::rotateOperationCopy(const double& dAngle)
{
    if(m_pOperationCopy)
    {
        m_pOperationCopy->setRotation(dAngle);
    }

}

void GraphicsItemGroup::updateBoundingRectFromChildren()
{
    m_boundingRect = QGraphicsItemGroup::boundingRect();
    m_dWidth = m_boundingRect.width();
    m_dHeight = m_boundingRect.height();
    updateHandles();
}

void GraphicsItemGroup::addItems(const QList<QGraphicsItem*>& items)
{
    foreach (QGraphicsItem *item, items)
    {
        item->setSelected(false);
        addToGroup(item);
        //m_listItem.push_back(item);
    }

    updateCoordinate();
}
