package io.github.alyphen.amethyst.client.panel;

import io.github.alyphen.amethyst.client.AmethystClient;
import io.github.alyphen.amethyst.common.entity.EntityCharacter;
import io.github.alyphen.amethyst.common.tile.Tile;
import io.github.alyphen.amethyst.common.world.World;
import io.github.alyphen.amethyst.common.world.WorldArea;

import javax.swing.*;
import java.awt.*;

public class WorldPanel extends JPanel {

    private AmethystClient client;

    private boolean active;
    private World world;
    private WorldArea area;
    private EntityCharacter playerCharacter;

    public WorldPanel(AmethystClient client) {
        this.client = client;
    }

    public void onTick() {
        world.onTick();
        repaint();
    }

    @Override
    public void paintComponent(Graphics graphics) {
        if (getArea() != null && getPlayerCharacter() != null) {
            Graphics2D graphics2D = (Graphics2D) graphics;
            graphics2D.translate(getCameraX(), getCameraY());
            for (int row = 0; row < area.getRows(); row++) {
                for (int col = 0; col < area.getColumns(); col++) {
                    Tile tile = getArea().getTileAt(row, col);
                    int x = col * tile.getSheet().getTileWidth();
                    int y = row * tile.getSheet().getTileHeight();
                    if (x + tile.getSheet().getTileWidth() >= getCameraX() - (getWidth() / 2)
                            && x <= getCameraX() + (getWidth() / 2)
                            && y + tile.getSheet().getTileHeight() >= getCameraY() - (getHeight() / 2)
                            && y <= getCameraY() + (getHeight() / 2))
                        tile.paint(graphics, x, y);
                }
            }
            getArea().getObjects().stream().filter(object -> object.getX() + object.getBounds().getWidth() >= getCameraX() - (getWidth() / 2)
                    && object.getX() <= getCameraX() + (getWidth() / 2)
                    && object.getY() + object.getBounds().getHeight() >= getCameraY() - (getHeight() / 2)
                    && object.getY() <= getCameraY() + (getHeight() / 2)).forEach(object -> {
                graphics2D.translate(object.getX(), object.getY());
                object.paint(graphics);
                graphics2D.translate(-object.getX(), -object.getY());
            });
            getArea().getEntities().stream().filter(entity -> entity.getX() + entity.getBounds().getWidth() >= getCameraX() - (getWidth() / 2)
                    && entity.getX() <= getCameraX() + (getWidth() / 2)
                    && entity.getY() + entity.getBounds().getHeight() >= getCameraY() - (getHeight() / 2)
                    && entity.getY() <= getCameraY() + (getHeight() /2)).forEach(entity -> {
                graphics2D.translate(entity.getX(), entity.getY());
                entity.paint(graphics);
                graphics2D.translate(-entity.getX(), -entity.getY());
            });
            graphics2D.translate(-getCameraX(), -getCameraY());
        }
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public World getWorld() {
        return world;
    }

    public void setWorld(World world) {
        this.world = world;
    }

    public WorldArea getArea() {
        return area;
    }

    public void setArea(WorldArea area) {
        world.addArea(area);
        if (this.area != null) world.removeArea(this.area);
        this.area = area;
    }

    public EntityCharacter getPlayerCharacter() {
        return playerCharacter;
    }

    public void setPlayerCharacter(EntityCharacter player) {
        this.playerCharacter = player;
    }

    private int getCameraX() {
        return (getWidth() / 2) - getPlayerCharacter().getX();
    }

    private int getCameraY() {
        return (getHeight() / 2) - getPlayerCharacter().getY();
    }

}

@@ -961,16 +961,17 @@
 anslate(
+-
 getCamer
@@ -976,16 +976,17 @@
 eraX(), 
+-
 getCamer
@@ -1391,35 +1391,16 @@
 ameraX()
- - (getWidth() / 2)
 %0A       
@@ -1435,33 +1435,32 @@
  getCameraX() + 
-(
 getWidth() / 2)%0A
@@ -1445,37 +1445,32 @@
 X() + getWidth()
- / 2)
 %0A               
@@ -1536,36 +1536,16 @@
 ameraY()
- - (getHeight() / 2)
 %0A       
@@ -1580,33 +1580,32 @@
  getCameraY() + 
-(
 getHeight() / 2)
@@ -1599,21 +1599,16 @@
 Height()
- / 2)
 )%0A      
@@ -1807,35 +1807,16 @@
 ameraX()
- - (getWidth() / 2)
 %0A       
@@ -1855,33 +1855,32 @@
  getCameraX() + 
-(
 getWidth() / 2)%0A
@@ -1865,37 +1865,32 @@
 X() + getWidth()
- / 2)
 %0A               
@@ -1959,36 +1959,16 @@
 ameraY()
- - (getHeight() / 2)
 %0A       
@@ -2007,33 +2007,32 @@
  getCameraY() + 
-(
 getHeight() / 2)
@@ -2026,21 +2026,16 @@
 Height()
- / 2)
 ).forEac
@@ -2369,27 +2369,8 @@
 aX()
- - (getWidth() / 2)
 %0A   
@@ -2421,17 +2421,16 @@
 raX() + 
-(
 getWidth
@@ -2431,21 +2431,16 @@
 tWidth()
- / 2)
 %0A       
@@ -2521,28 +2521,8 @@
 aY()
- - (getHeight() / 2)
 %0A   
@@ -2573,17 +2573,16 @@
 raY() + 
-(
 getHeigh
@@ -2588,12 +2588,8 @@
 ht()
- /2)
 ).fo
@@ -2825,33 +2825,32 @@
 ics2D.translate(
--
 getCameraX(), -g
@@ -2839,33 +2839,32 @@
 e(getCameraX(), 
--
 getCameraY());%0A 
@@ -3626,27 +3626,8 @@
 turn
- (getWidth() / 2) -
  get
@@ -3650,16 +3650,35 @@
 ).getX()
+ - (getWidth() / 2)
 ;%0A    %7D%0A
@@ -3727,28 +3727,8 @@
 turn
- (getHeight() / 2) -
  get
@@ -3751,16 +3751,36 @@
 ).getY()
+ - (getHeight() / 2)
 ;%0A    %7D%0A

Fix rendering