#include "pipe.h"
#include "plant.h"
#include <render/render.h>
#include <string.h>
#include <resources.h>
#include <algorithm>

namespace game{

pipe::pipe(const vec2f &pos, level *root):basicPipe(pos, vec2u(1), root)
{
    _capacity = 32;
    _lockedItem = -1;
    _needShowGui = false;
    memset(_undergroundConnections, 0, 4*sizeof(pipe*));
    _type = rand()%4;
    _mathMask();
}

pipe::~pipe()
{
    for(int i = 0; i < 4; i++)
        if(_undergroundConnections[i])
            _undergroundConnections[i]->_removeUndergroundPipe(this,i,true);
}

void pipe::beforeNeighbourDestroyed(entity *ent)
{
    basicPipe::beforeNeighbourDestroyed(ent);
    _needRemathMask = true;
}

void pipe::onNeighbourCreated(entity *ent)
{
    basicPipe::onNeighbourCreated(ent);
    _needRemathMask = true;
}

void pipe::_mathMask()
{
    _drawMask = 0;
    for(int i = 0; i < 4; i++)
        if(cell *c = _cells[0]->sibling(i))
            if(entity *e = c->get())
            {
                if(pipe *p = dynamic_cast<pipe*>(e))
                {
                    if((p->_item == _item || _item == 0xFFFFFFFF || p->_item == 0xFFFFFFFF) && (_lockedItem == -1 || p->_lockedItem == -1 || _lockedItem == p->_lockedItem))
                        _drawMask |= 1<<i;
                }
                else
                    _drawMask |= 1<<i;
            }

    _needRemathMask = false;
}

void pipe::hover() noexcept
{
    _needShowShortInfo = true;
}

void pipe::onGui() noexcept
{
    if(_needShowShortInfo && !_needShowGui)
    {
        _drawShortInfo();
        _needShowShortInfo = false;
    }

    if(!_needShowGui)
        return;

    if(currentlyShown != this)
    {
        _needShowGui = false;
        return;
    }
    _drawWindow();
}

float pipe::add(uint item, float amount) noexcept
{
    if(_item != 0xFFFFFFFF && _item != item && _amount > 0.05)
        return 0; // смешивать не будем

    if(_capacity - _amount < 0.05)
        return 0;

    // будем принимать только разрешенные вещи
    if(item != _lockedItem && _lockedItem != 0xFFFFFFFF)
        return 0;

    if(item != _item)
        _mathMask();

    _item = item;

    float newAmount = _amount+amount;
    if(newAmount >= _capacity)
    {
        _amount = _capacity;
        return amount-(newAmount - _capacity); // вернем что потратили
    }
    _amount += amount;

    return amount;
}

void pipe::draw()
{
    if(_needRemathMask)
        _mathMask();

    for(int i = 0; i < 2; i++)
        if(_undergroundConnections[i])
        {
            vec2u size = _undergroundConnections[i]->_pos-_pos;
            if(size.x)
                for(int x = 0; x <= size.x; x++)
                    resources::atlas.draw(_pos+vec2u(x,0),vec2u(6,14));
            else if(size.y)
                for(int x = 0; x <= size.y; x++)
                    resources::atlas.draw(_pos+vec2u(0,x),vec2u(5,14));

                //for(int y = 0; y < size.y; y++)
                    //resources::atlas.draw()


            //render::primitives2d::quad(vec2f(_pos)+vec2f(0.25), size, rgba(1,1,1,.1));
        }

    resources::atlas.draw(_pos,vec2u(_drawMask,_type));


    if(_needShowGui)
        resources::atlas.draw(_pos,vec2u(0,14));
    else if(_needShowShortInfo)
        resources::atlas.draw(_pos,vec2u(0,13));

    if(_item != 0xFFFFFFFF && _amount >= 0.05)
        render::primitives2d::quad(_pos, vec2f(_size.x, getFilledSpace()*_size.y), getItemById(_item)->color);
}

bool pipe::_addUndergroundPipe(pipe *p, uint32_t dir, bool r)
{
    if(basicPipe *b = dynamic_cast<basicPipe*>(p))
        if(std::find(_connections.begin(),_connections.end(),b) != _connections.end())
            return false;

    if(r)
        dir = (dir+2)%4; // попорачиваем на 180 градусов :D
    if(_undergroundConnections[dir])
        return false;
    _undergroundConnections[dir] = p;
    _connections.push_back(p);
    _connections.unique();
    return true;
}

void pipe::_removeUndergroundPipe(pipe *p, uint32_t dir, bool r)
{
    if(r)
        dir = (dir+2)%4; // попорачиваем на 180 градусов :D
    if(_undergroundConnections[dir] != p)
        return;
    _undergroundConnections[dir] = 0;
    _connections.remove(p);
}

pipe *pipe::_findPipe(uint32_t dir)
{
    cell *c = _cells[0];
    for(int i = 0; i < 10; i++)
    {
        c = c->sibling(dir);
        if(!c)
            return nullptr;
        if(pipe *p = dynamic_cast<pipe*>(c->get()))
            if(p->_item == 0xFFFFFFFF || p->_item == _item || _item == 0xFFFFFFFF || p->_amount < 0.05 || _amount < 0.05)
                return p;

    }
    return nullptr;
}

}
