import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Stack;

public class MapWithSetShipsGeneric<T extends IDrawingObject, U extends  AbstractMap> {
    private final int _pictureWidth;
    private final int _pictureHeight;
    private final int _placeSizeWidth = 210;
    private final int _placeSizeHeight = 90;
    private final SetShipGeneric<T> _setShips;
    private final U _map;
    private Stack<T> _deletedShips;
    public MapWithSetShipsGeneric(int picWidth, int picHeight, U map)
    {
        _deletedShips=new Stack<>();
        int width = picWidth / _placeSizeWidth;
        int height = picHeight / _placeSizeHeight;
        _setShips = new SetShipGeneric<T>(width * height);
        _pictureWidth = picWidth;
        _pictureHeight = picHeight;
        _map = map;
    }
    public int Add(T ship)
    {
        return _setShips.Insert(ship);
    }
    public T Delete(int position)
    {
        T ship=_setShips.Remove(position);
        _deletedShips.push(ship);
        return ship;
    }
    public BufferedImage ShowSet()
    {
        BufferedImage bmp = new BufferedImage(_pictureWidth,_pictureHeight,BufferedImage.TYPE_INT_RGB);
        Graphics gr = bmp.getGraphics();
        DrawBackground(gr);
        DrawShips(gr);
        return bmp;
    }
    public BufferedImage ShowOnMap()
    {
        Shaking();
        for (var ship : _setShips)
        {
            return _map.CreateMap(_pictureWidth,_pictureHeight,ship);
        }
        return new BufferedImage(_pictureWidth, _pictureHeight, BufferedImage.TYPE_INT_RGB);
    }
    public T GetSelectedShip(int ind){
        return _setShips.Get(ind);
    }
    public T GetShipsDeleted()
    {
        if(_deletedShips.isEmpty())
        {
            return null;
        }
        return _deletedShips.pop();
    }
    public BufferedImage MoveObject(Direction direction)
    {
        if (_map != null)
        {
            return _map.MoveObject(direction);
        }
        return new BufferedImage(_pictureWidth, _pictureHeight, BufferedImage.TYPE_INT_RGB);
    }
    private void Shaking()
    {
        int j = _setShips.Count() - 1;
        for (int i = 0; i < _setShips.Count(); i++)
        {
            if (_setShips.Get(i) == null)
            {
                for (; j > i; j--)
                {
                    var ship = _setShips.Get(j);
                    if (ship != null)
                    {
                        _setShips.Insert(ship, i);
                        _setShips.Remove(j);
                        break;
                    }
                }
                if (j <= i)
                {
                    return;
                }
            }
        }
    }
    private void DrawBackground(Graphics gr)
    {
        Graphics2D g = (Graphics2D) gr;
        g.setColor(Color.blue);
        g.fillRect( 0, 0, _pictureWidth, _pictureHeight);

        for (int i = 0; i < _pictureWidth / _placeSizeWidth; i++)
        {
            for (int j = 0; j < _pictureHeight / _placeSizeHeight; ++j)
            {
                g.setColor(new Color(90, 41, 19));
                g.setStroke(new BasicStroke(3));

                g.drawLine(i * _placeSizeWidth, j * _placeSizeHeight + _placeSizeHeight/2, i *
                        _placeSizeWidth + _placeSizeWidth / 2, j * _placeSizeHeight + _placeSizeHeight / 2);

                for(int k = 1; k < 3; ++k)
                {
                    g.setColor(new Color(2, 2, 2));
                    g.setStroke(new BasicStroke(1));
                    g.drawLine(i * _placeSizeWidth, j * _placeSizeHeight + k * 21, i *
                            _placeSizeWidth + 3 * _placeSizeWidth / 10, j * _placeSizeHeight + k * 21);
                }

                for (int k = 0; k < 4; ++k)
                {
                    g.setColor(new Color(90, 41, 19));
                    g.setStroke(new BasicStroke(5));
                    g.drawLine(i * _placeSizeWidth + k * _placeSizeWidth / 10, j * _placeSizeHeight + 20, i * _placeSizeWidth + k * _placeSizeWidth / 10,
                            (j + 1) * _placeSizeHeight - 20);
                }
            }
        }
    }
    private void DrawShips(Graphics g)
    {
        int xNumOfPlaces   = _pictureWidth / _placeSizeWidth;
        int yNumOfPlaces  = _pictureHeight / _placeSizeHeight;
        int RowIndex = yNumOfPlaces - 1;
        int ColumnIndex = xNumOfPlaces - 1;
        for (int i = 0; i < _setShips.Count(); i++)
        {
            if(_setShips.Get(i)==null)
            {
                continue;
            }
            _setShips.Get(i).SetObject(ColumnIndex * _placeSizeWidth,
                    RowIndex * _placeSizeHeight + (_placeSizeHeight - (int)(_setShips.Get(i).GetCurrentPosition()[3] - _setShips.Get(i).GetCurrentPosition()[1])),
                    _pictureWidth, _pictureHeight);
            _setShips.Get(i).DrawingObject(g);
            if (ColumnIndex == 0) {
                ColumnIndex = xNumOfPlaces - 1;
                RowIndex--;
            }else
            {
                ColumnIndex--;
            }
            if (ColumnIndex > yNumOfPlaces)
            {
                return;
            }
        }
    }
}