#include "ad_graphics.h"
#include <QGLWidget>
#include <QGraphicsItem>



AD_Graphics::AD_Graphics(AD_Core *adcore, QWidget *parent) : QGraphicsView(parent) , color_curve(QEasingCurve::InQuad)
{
    focus_item = select_tow = select_al = 0;
    data = adcore->addata;
    core = adcore;
    setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
    setAlignment(Qt::AlignLeft | Qt::AlignTop);
    setMouseTracking(true);
    scene = new QGraphicsScene();
    scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    core->setScene(scene);
    setScene(scene);
    selection_al = new ADItem(-1, ADItem::Other, core->addata->alienSelect.images);
    selection_al->hide();
    selection_tow = new ADItem(-1, ADItem::Other, core->addata->towerSelect.images);
    selection_tow->hide();
    scene->addItem(selection_al);
    scene->addItem(selection_tow);
    //setCacheMode();
    //setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    mapimg = new QImage(data->map->rect().size()*cellSize,QImage::Format_ARGB32);
    //setDragMode(RubberBandDrag);
    QPainter p(mapimg);
    p.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
    for (int i=0; i<data->map->cells().size(); i++) {
        for (int j=0; j<data->map->cells().at(i).size(); j++) {
            QPen pen;
            QBrush brush;
            pen.setColor(Qt::white);
            brush.setColor(Qt::white);
            brush.setStyle(Qt::SolidPattern);
            int cel = data->map->cells().at(i).at(j);
            if (cel == Map::Wall)
            {
                pen.setColor(Qt::black);
                brush.setColor(Qt::black);
            }
            if (cel >= Map::Free || (cel <= Map::PlayerTower && cel !=Map::Wall))
            {
                pen.setColor(QColor(qAbs(cel+2)*345%100,(qAbs(cel+2)*721)%100,(qAbs(cel+2)*75)%100).lighter());
                brush.setColor(QColor(qAbs(cel+2)*345%255,(qAbs(cel+2)*721)%255,(qAbs(cel+2)*75)%255).lighter());
            }
            p.setPen(pen);
            p.setBrush(brush);
            p.drawRect(i*cellSize,j*cellSize,cellSize,cellSize);
        }
    }
    p.end();
    scene->setSceneRect(mapimg->rect());
    //scene->setBackgroundBrush(*mapimg);
    setCacheMode(QGraphicsView::CacheBackground);
    setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
    resize(mapimg->size());
    m_scale.reset();
    startTimer(50);
}


AD_Graphics::~AD_Graphics()
{
    delete selection_tow;
    delete selection_al;
    delete scene;
}


void AD_Graphics::mousePressEvent(QMouseEvent *event)
{
    //    scene->clearSelection();
    if (event->button() == Qt::LeftButton)
    {
        if (m_building)
            emit add_tow((QPointF(mapToScene(event->pos())/cellSize).toPoint()),
                         event->modifiers().testFlag(Qt::ShiftModifier));
        else
        {
            QList<QGraphicsItem*> list = scene->items(mapToScene(event->pos()), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder);
            ADItem * al = 0;
            foreach(QGraphicsItem* x, list)
            {
                ADItem * i = qgraphicsitem_cast<ADItem*>(x);
                if (i->itemType() == ADItem::Tower)
                {
                    //                    i->setSelected(true);
                    select_tow = i;
                    emit selected_tower_changed(i->tid());
                    return;
                }
                if (i->itemType() == ADItem::Alien)
                {
                    al = i;
                }
            }
            if (al != 0)
            {
                //                al->setSelected(true);
                select_al = al;
                core->addata->players.at(0)->selectAlienId = select_al->id();
                return;
            }
        }
    }
    if (event->button() == Qt::RightButton)
    {
        select_al = 0;
        select_tow = 0;
        emit selected_tower_changed(QPoint());
        emit cancel();
    }
}


void AD_Graphics::timerEvent(QTimerEvent * )
{
    if (select_al != 0)
    {
        selection_al->setPos(select_al->pos());
        selection_al->show();
    } else selection_al->hide();
    if (select_tow != 0)
    {
        selection_tow->setPos(select_tow->pos());
        selection_tow->show();
    } else selection_tow->hide();
    selection_tow->next();
    selection_al->next();
    if (core->isWaveEnd())
        scene->update();
    QList<int> moneyitemsdeads;
    for(int i=0; i<moneyitems.size(); i++)
    {
        float op = moneyitems[i]->opacity();
        moneyitems[i]->setOpacity(op - (1-op*0.999));
        moneyitems[i]->moveBy(0.2,-0.4);
        moneyitems[i]->setScale(moneyitems[i]->scale()+0.1);
        if (op < 0.1)
        {
            moneyitemsdeads.append(i);
        }
    }
    for (int i=0; i<moneyitemsdeads.size(); i++)
    {
		//scene->removeItem(moneyitems[i]);
        delete moneyitems[moneyitemsdeads.at(i)];
        //moneyitems.removeAt(moneyitemsdeads.at(i));
    }
}


void AD_Graphics::drawBackground(QPainter * p, const QRectF & r)
{
    p->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
    p->fillRect(r,Qt::black);
    p->drawImage(0,0,*mapimg);
}


void AD_Graphics::drawForeground(QPainter *p, const QRectF &rect)
{
    p->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
    QList <QGraphicsItem *> l = scene->items();
    foreach(QGraphicsItem * g,l)
    {
        ADItem * i = qgraphicsitem_cast<ADItem *>(g);
        if (i->isBarVisible())
        {
            p->setPen(Qt::black);
            p->setBrush(Qt::NoBrush);
            p->drawRect(i->pos().x()-cellSize-1,i->pos().y()-cellSize*1.25-1,cellSize*2+2,cellSize/4+2);
            p->setPen(Qt::NoPen);
            p->setBrush(QBrush(QColor::fromHsv(120*color_curve.valueForProgress(i->value()),230,230)));
            p->drawRect(i->pos().x()-cellSize,i->pos().y()-cellSize*1.25,cellSize*2*i->value(),cellSize/4);
        }
    }
    if (focus_item != 0)
    {
        if (focus_item->itemType() == ADItem::Tower)
        {
            float r = core->addata->curTowers[focus_item->tid()].src->radius*cellSize;
            QPen pen;
            QBrush b;
            b.setStyle(Qt::SolidPattern);
            b.setColor(QColor(100,240,100,80));
            pen.setColor(QColor(240,50,50,100));
            pen.setStyle(Qt::DashDotLine);
            pen.setWidthF(2.5);
            p->setPen(pen);
            p->setBrush(b);
            p->drawEllipse(focus_item->pos(), r, r);
        }
    }
}


void AD_Graphics::mouseMoveEvent(QMouseEvent *event)
{
    QList<QGraphicsItem * > li = scene->items(mapToScene(event->pos()), Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
    foreach (QGraphicsItem * i, li) {
        if (qgraphicsitem_cast<ADItem *>(i)->itemType() == ADItem::Tower) {
            focus_item = qgraphicsitem_cast<ADItem *>(i);
            //            selection_tow->setPos(focus_item->pos());
            //            selection_tow->show();
            return;
        }
    }
    //    selection_tow->hide();
    focus_item = 0;
}

void AD_Graphics::alienKilled(int id, bool missed)
{
    if (select_al != 0) if (select_al->id() == id) select_al = 0;
    QPointF alpos = core->addata->aliens->curAliens[id].pos;
    if (missed)
    {
        MoneyItem * lm = new MoneyItem();
        lm->setPos(QPointF(mapimg->width()/2+qrand()%20,mapimg->height()/2+qrand()%20));
        lm->setText("missed");
        lm->setColor(Qt::red);
        lm->setScale(5);
        moneyitems.append(lm);
        scene->addItem(lm);
        return;
    }
    QPainter p(mapimg);
    //p.setCompositionMode(QPainter::CompositionMode_Plus);
    p.translate((alpos+QPointF(0.5,0.5))*cellSize);
    p.rotate(qrand()%90);
    p.drawImage(core->addata->bloodrect, *(core->addata->blood));
    p.end();
    resetCachedContent();
    MoneyItem * m = new MoneyItem();
    m->setPos(alpos*cellSize);
    m->setMoney(core->addata->aliens->curAliens[id].src->prise);
    moneyitems.append(m);
    scene->addItem(m);
}


void AD_Graphics::resizeEvent(QResizeEvent *event)
{
    m_scale.reset();
    float f = static_cast<float>(qMin(event->size().width(),event->size().height()))/mapimg->size().width();
    m_scale.scale(f,f);
    setTransform(m_scale);
    repaint();
}

